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 f5c1086f54..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,12 +62,13 @@ 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
+ if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.gitignore b/.gitignore
index f7a8dad973..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,12 +168,29 @@ 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
+/imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-mago-burst-in.csv
+/imap_processing/tests/mag/validation/L1c/T015/mag-l1b-l1c-t015-mago-burst-in.csv
+/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-burst-in.csv
+/imap_processing/tests/mag/validation/L2/T021/imap_mag_l2_burst-offsets_20250506_v006.cdf
+/imap_processing/tests/mag/validation/L2/T021/imap_mag_l2_burst_20250506_v007.csv
+/imap_processing/tests/mag/validation/L2/T021/mag-l1bc-l2-t021-magi-burst-in.csv
+/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 d8e174d042..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.2'
+ rev: "v0.15.2"
hooks:
- - id: ruff
- 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)
-[](#contributors-)
+[](#contributors-)
[](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
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 98%
rename from docs/source/code-documentation/spice.rst
rename to docs/source/algorithm-code-documentation/spice.rst
index 982aca426d..66d722ceaf 100644
--- a/docs/source/code-documentation/spice.rst
+++ b/docs/source/algorithm-code-documentation/spice.rst
@@ -22,7 +22,6 @@ table data.
:recursive:
geometry
- kernels
repoint
spin
time
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 92%
rename from docs/source/data-access/naming-conventions.rst
rename to docs/source/filename-convention/naming-conventions.rst
index 55f887d339..8ffacf3afa 100644
--- a/docs/source/data-access/naming-conventions.rst
+++ b/docs/source/filename-convention/naming-conventions.rst
@@ -36,8 +36,8 @@ The general filename convention is as follows::
* CoDICE: ``hskp``, ``lo-counters-aggregated``, ``lo-counters-singles``, ``hi-counters-aggregated``,
``hi-counters-singles``, ``hi-priorities``, ``lo-sw-priority``, ``lo-nsw-priority``, ``lo-sw-angular``,
- ``lo-nsw-angular``, ``lo-pha``, ``hi-pha``, ``lo-sw-species``, ``lo-nsw-species``, ``hi-omni``, ``hi-sectored``,
- ``lo-ialirt``, ``hi-ialirt``
+ ``lo-nsw-angular``, ``lo-direct-events``, ``hi-direct-events``, ``lo-sw-species``, ``lo-nsw-species``, ``hi-omni``,
+ ``hi-sectored``, ``lo-ialirt``, ``hi-ialirt``
* GLOWS: ``hist``, ``de``, ``lightcurve``, ``ionization-rate``, ``survival-probabilities``
* HIT: TBD
* IDEX: ``sci``
@@ -65,9 +65,9 @@ Here are a few examples of acceptable filenames:
An IDEX L0 packet file containing data from the single day of ``2026-12-06``
-* ``imap_codice_l1a_lo-pha_20261206_v001.cdf``
+* ``imap_codice_l1a_lo-direct-events_20261206_v001.cdf``
- A version ``001`` CoDICE-Lo L1a data product called ``pha`` containing data from ``2026-12-06``
+ A version ``001`` CoDICE-Lo L1a data product called ``direct-events`` containing data from ``2026-12-06``
* ``imap_glows_l1a_counts_20261206-repoint00002_v001.cdf``
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 b9afcebb18..9cd8bd2b68 100644
--- a/imap_processing/ancillary/ancillary_dataset_combiner.py
+++ b/imap_processing/ancillary/ancillary_dataset_combiner.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+import json
from collections import namedtuple
from pathlib import Path
@@ -122,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)
@@ -144,7 +145,53 @@ def convert_file_to_dataset(self, filepath: str | Path) -> xr.Dataset:
"""
return cdf_to_xarray(filepath)
- def _combine_input_datasets(self) -> xr.Dataset:
+ @staticmethod
+ def convert_json_to_dataset(filepath: str | Path) -> xr.Dataset:
+ """
+ Read a JSON file and convert it to an xarray Dataset.
+
+ This method handles JSON files by converting them to xarray Datasets
+ with appropriate structure. Nested dictionaries are flattened using
+ underscore separation, up to 2 levels deep.
+
+ Parameters
+ ----------
+ filepath : str | Path
+ The path to the JSON file to convert.
+
+ Returns
+ -------
+ xr.Dataset
+ The converted xarray dataset with JSON data as data variables.
+ """
+ with open(filepath) as f:
+ json_data = json.load(f)
+
+ # Convert JSON data to xarray Dataset with appropriate structure
+ # Each top-level key becomes a data variable
+
+ # The structure of the dictionary is {: (dims, data)}
+ # For the lists, we specify the dimension names. For scalars, pass in [].
+ data_vars = {}
+ for key, value in json_data.items():
+ if isinstance(value, (list, tuple)):
+ # Handle arrays/lists
+ data_vars[key] = ([f"dim_{key}"], value)
+ elif isinstance(value, dict):
+ # Handle nested dictionaries by flattening with underscore
+ for subkey, subvalue in value.items():
+ flat_key = f"{key}_{subkey}"
+ if isinstance(subvalue, (list, tuple)):
+ data_vars[flat_key] = ([f"dim_{flat_key}"], subvalue)
+ else:
+ data_vars[flat_key] = ([], subvalue)
+ else:
+ # Handle scalar values
+ data_vars[key] = ([], value)
+
+ return xr.Dataset(data_vars)
+
+ def _combine_input_datasets(self) -> xr.Dataset: # noqa: PLR0912
"""
Combine all the input datasets into one output dataset.
@@ -167,6 +214,10 @@ def _combine_input_datasets(self) -> xr.Dataset:
"""
output_dataset = xr.Dataset()
+ # Handle empty input gracefully
+ if not self.timestamped_data:
+ return output_dataset
+
full_range_start = None
full_range_end = None
for timestamped_data in self.timestamped_data:
@@ -180,7 +231,7 @@ def _combine_input_datasets(self) -> xr.Dataset:
# 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(
@@ -258,3 +309,138 @@ def __init__(
expected_end_date: np.datetime64 | str,
):
super().__init__(ancillary_input, expected_end_date)
+
+
+class GlowsAncillaryCombiner(AncillaryCombiner):
+ """
+ GLOWS-specific instance of AncillaryConverter for bad-angle flag data.
+
+ This class handles GLOWS ancillary files for L1B processing, including:
+ - Excluded regions map (.dat files with ecliptic coordinates)
+ - UV sources map (.dat files with star positions and masking radii)
+ - Suspected transients (.dat files with time-based histogram masks)
+ - Instrument team exclusions (.dat files with time-based histogram masks)
+
+ Parameters
+ ----------
+ ancillary_input : ProcessingInput
+ Collection of GLOWS ancillary files.
+ expected_end_date : np.datetime64 | str
+ The expected end date of the dataset. This is used to fill in the end date
+ of the dataset if it is not provided in the input file. This should either
+ be a numpy datetime64 object or a string in the format YYYYMMDD.
+ """
+
+ def __init__(
+ self,
+ ancillary_input: ProcessingInput | list[Path],
+ expected_end_date: np.datetime64 | str,
+ ):
+ super().__init__(ancillary_input, expected_end_date)
+
+ def convert_file_to_dataset(self, filepath: str | Path) -> xr.Dataset: # noqa: PLR0911
+ """
+ Convert GLOWS ancillary .dat files to xarray datasets.
+
+ This method handles different types of GLOWS ancillary files:
+ - excluded_regions: longitude/latitude coordinate pairs
+ - uv_sources: star names with coordinates and masking radii
+ - suspected_transients: time-based histogram masks
+ - exclusions_by_instr_team: time-based histogram masks
+
+ Parameters
+ ----------
+ filepath : str | Path
+ The path to the GLOWS ancillary file to convert.
+
+ Returns
+ -------
+ xr.Dataset
+ The converted xarray dataset with appropriate dimensions and variables.
+ """
+ filepath = Path(filepath)
+ filename = filepath.name
+
+ 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]),
+ "ecliptic_latitude_deg": (["region"], data[:, 1]),
+ }
+ )
+
+ elif "uv-sources" in filename:
+ # Handle UV sources (4 columns: name, longitude, latitude, radius)
+ data = np.loadtxt(filepath, comments="#", dtype=str)
+ return xr.Dataset(
+ {
+ "object_name": (["source"], data[:, 0]),
+ "ecliptic_longitude_deg": (["source"], data[:, 1].astype(float)),
+ "ecliptic_latitude_deg": (["source"], data[:, 2].astype(float)),
+ "angular_radius_for_masking": (
+ ["source"],
+ data[:, 3].astype(float),
+ ),
+ }
+ )
+
+ elif "suspected-transients" in filename:
+ # Handle suspected transients (time identifier + mask string)
+ 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]
+ masks = [line.split(" ", 1)[1] for line in lines]
+ return xr.Dataset(
+ {
+ "l1b_unique_block_identifier": (["time_block"], identifiers),
+ "histogram_mask_array": (["time_block"], masks),
+ }
+ )
+
+ elif "exclusions-by-instr-team" in filename:
+ # Handle instrument team exclusions (time identifier + mask string)
+ 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]
+ masks = [line.split(" ", 1)[1] for line in lines]
+ return xr.Dataset(
+ {
+ "l1b_unique_block_identifier": (["time_block"], identifiers),
+ "histogram_mask_array": (["time_block"], masks),
+ }
+ )
+
+ 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)
+
+ else:
+ raise ValueError(f"Unknown GLOWS ancillary file type: {filename}")
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 d95fc9c3c7..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,85 +1,38 @@
# <=== 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:
@@ -90,8 +43,8 @@ esa_step:
LABLAXIS: Energy Index
SCALETYP: linear
UNITS: " "
- VALIDMIN: 0
VALIDMAX: 127
+ VALIDMIN: 0
VAR_TYPE: support_data
event_num:
@@ -102,8 +55,8 @@ event_num:
LABLAXIS: Event Number
SCALETYP: linear
UNITS: " "
- VALIDMIN: 0
VALIDMAX: 10000
+ VALIDMIN: 0
VAR_TYPE: support_data
inst_az:
@@ -114,8 +67,8 @@ inst_az:
LABLAXIS: Azimuth Index
SCALETYP: linear
UNITS: " "
- VALIDMIN: 0
VALIDMAX: 31
+ VALIDMIN: 0
VAR_TYPE: support_data
spin_sector:
@@ -126,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 ===>
@@ -195,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
@@ -209,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
@@ -227,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
@@ -267,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
@@ -345,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
@@ -359,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
@@ -374,3059 +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-LowTOFCutoff:
- <<: *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-ASIC1FlagInvalid:
- <<: *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-ASIC2FlagInvalid:
- <<: *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-ASIC1ChannelInvalid:
- <<: *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-ASIC2ChannelInvalid:
- <<: *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_delta
- DELTA_PLUS_VAR: energy_h_delta
-
-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 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_delta
- DELTA_PLUS_VAR: energy_h_delta
-
-hi-omni-energy_h_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for h
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_he3_delta
-
-hi-omni-energy_he3_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for he3
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_he4_delta
-
-hi-omni-energy_he4_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for he4
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_c_delta
-
-hi-omni-energy_c_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for c
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_o_delta
-
-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 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_delta
- DELTA_PLUS_VAR: energy_ne_mg_si_delta
-
-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 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_delta
- DELTA_PLUS_VAR: energy_fe_delta
-
-hi-omni-energy_fe_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for fe
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_uh_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_junk_delta
-
-hi-omni-energy_junk_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for junk
- FIELDNAM: Delta Energy
# 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_delta
- DELTA_PLUS_VAR: energy_h_delta
-
-hi-sectored-energy_h_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for H
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_he3he4_delta
-
-hi-sectored-energy_he3he4_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for He3He4
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_cno_delta
-
-hi-sectored-energy_cno_delta:
- <<: *hi_energies_default
- CATDESC: Delta of energies for CNO
- FIELDNAM: Delta Energy
-
-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_delta
- DELTA_PLUS_VAR: energy_fe_delta
-
-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 ===>
+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-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-tcr:
+ <<: *lo_counters_aggregated_default
+ CATDESC: Triple Coincidence Rate (TCR)
+ FIELDNAM: Event A - TCR
-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-dcr:
+ <<: *lo_counters_aggregated_default
+ CATDESC: Double Coincidence Rate (DCR)
+ FIELDNAM: Event B - DCR
-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-low_tof_cutoff:
+ <<: *lo_counters_aggregated_default
+ CATDESC: Low TOF Cutoff
+ FIELDNAM: Low TOF Cutoff
-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-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-counters-aggregated-STAorSTBPlusAPD:
- <<: *events
+lo-position_only:
+ <<: *lo_counters_aggregated_default
+ CATDESC: Position Only
+ FIELDNAM: Event F - Position Only
+
+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-STAorSTBOnly:
- <<: *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-SPOnly:
- <<: *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-APDOnly:
- <<: *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-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
+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-TotalPositionCount:
- <<: *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-InvalidPositionCount:
- <<: *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-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
+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-TEC4TimeoutPosNoTOF:
- <<: *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-TEC4TimeoutNoPosTOF:
- <<: *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-TEC5TimeoutTOFNoPos:
- <<: *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-TEC5TimeoutPosNoTOF:
- <<: *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-TEC5TimeoutNoPosTOF:
- <<: *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 ===>
-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
+# 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_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
+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 ec04ab4123..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_delta
- DELTA_PLUS_VAR: energy_h_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_h_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_he3_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_he4_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_c_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_o_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_ne_mg_si_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_fe_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_uh_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_junk_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_h_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_he3he4_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_cno_delta
-
-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_delta
- DELTA_PLUS_VAR: energy_fe_delta
-
-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 4be1a75df6..0000000000
--- a/imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml
+++ /dev/null
@@ -1,1028 +0,0 @@
-# <=== Useful Variables ===>
-int_fillval: &int_fillval -9223372036854775808
-min_int: &min_int -9223372036854775808
-max_int: &max_int 9223372036854775807
-
-# <=== 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
-
-# <=== Coordinates ===>
-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
- 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
-
-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
-
-# <=== Labels ===>
-event_num_label:
- CATDESC: Event Number
- DEPEND_1: event_num
- FIELDNAM: Event Number
- FORMAT: A5
- VAR_TYPE: metadata
-
-# <=== Direct Events Attributes ===>
-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
- DICT_KEY: SPASE>Support>SupportQuantity:Other
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
- DICT_KEY: SPASE>Support>SupportQuantity:DataQuality
-
-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
\ No newline at end of file
diff --git a/imap_processing/cdf/config/imap_constant_attrs.yaml b/imap_processing/cdf/config/imap_constant_attrs.yaml
index 74d2024a28..5ca7d059f3 100644
--- a/imap_processing/cdf/config/imap_constant_attrs.yaml
+++ b/imap_processing/cdf/config/imap_constant_attrs.yaml
@@ -2,33 +2,35 @@
# center of accumulation/measurement period. But if, for some good reason,
# time corresponds to the beginning or end or any other part of
# accumulation/measurement period, that has to be stated in CATDESC.
+
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: -9223372036854775808
- VALIDMAX: 9223372036854775807
- 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 4c968647ce..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,15 +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: ' '
+ VALIDMAX: 2
+ VALIDMIN: 0
+ VAR_TYPE: support_data
+
+latitudinal_attrs:
+ <<: *default_attrs
+ CATDESC: Component index for cartesian latitudinal coordinates
+ FIELDNAM: Component index
+ FILLVAL: 999
+ FORMAT: I3
LABLAXIS: Index
UNITS: ' '
- FILLVAL: 255
+ VALIDMAX: 360
+ VALIDMIN: 0
VAR_TYPE: support_data
- FORMAT: I1
number_of_events:
<<: *support_data_defaults
@@ -246,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
@@ -278,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
@@ -291,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:
@@ -303,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:
@@ -317,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:
@@ -329,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
@@ -340,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
@@ -351,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
@@ -477,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
@@ -532,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
@@ -557,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
@@ -577,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
@@ -629,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
@@ -664,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:
@@ -712,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
@@ -729,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 bdc7c5fb40..9be70c4d15 100644
--- a/imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml
+++ b/imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml
@@ -39,18 +39,27 @@ imap_hi_l1a_hk_attrs:
Logical_source: imap_hi_l1a_{sensor}-hk
Logical_source_description: IMAP-Hi Instrument Level-1A Housekeeping Data.
+imap_hi_l1a_memdmp_attrs:
+ Data_type: L1A_HK>Level-1A Memory Dump
+ Logical_source: imap_hi_l1a_{sensor}-memdmp
+ Logical_source_description: IMAP-Hi Instrument Level-1A Memory Dump Data.
+
imap_hi_l1b_hk_attrs:
Data_type: L1B_HK>Level-1B Housekeeping
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 044a20b9cf..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:
@@ -17,11 +17,17 @@ imap_hit_l1a_hk:
Logical_source: imap_hit_l1a_hk
Logical_source_description: IMAP Mission HIT Instrument Level-1A Housekeeping Data.
-imap_hit_l1a_counts:
+imap_hit_l1a_counts-standard:
+ <<: *instrument_base
+ Data_type: L1A_counts>Level-1A Standard Counts
+ Logical_source: imap_hit_l1a_counts-standard
+ Logical_source_description: IMAP Mission HIT Instrument Level-1A Standard Count Rates Data.
+
+imap_hit_l1a_counts-sectored:
<<: *instrument_base
- Data_type: L1A_counts>Level-1A Counts
- Logical_source: imap_hit_l1a_counts
- Logical_source_description: IMAP Mission HIT Instrument Level-1A Count Rates Data.
+ Data_type: L1A_counts>Level-1A Sectored Counts
+ Logical_source: imap_hit_l1a_counts-sectored
+ Logical_source_description: IMAP Mission HIT Instrument Level-1A Sectored Count Rates Data.
imap_hit_l1a_direct-events:
<<: *instrument_base
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 580bae007b..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,327 +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
- UNITS: amu
- VALIDMIN: 0.0
+ FORMAT: F20.4
+ UNITS: Kg
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
-
-chi_square_base: &chi_square_base
- UNITS: " "
- VALIDMIN: 0.0
+ FORMAT: F20.4
+ UNITS: km/s
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>Support>SupportQuantity:DataQuality
-
-fit_results_base: &fit_results_base
- UNITS: pC
- VALIDMIN: 0
+ FORMAT: F20.4
+ UNITS: " "
VALIDMAX: *int_maxval
+ VALIDMIN: 0.0
VAR_TYPE: data
+
+fit_results_base: &fit_results_base
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: amu
+ 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: amu
- 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: amu
- 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
+ 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
+ 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
+ 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 02cd559c75..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,244 +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
-
-rectangular_lon_pixel_label:
- CATDESC: Longitude pixel index label for IDEX SkyMap.
- 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.
- FIELDNAM: Latitude pixel label
- FORMAT: A5
+ FIELDNAM: Spin Phase (deg)
+ FORMAT: A8
VAR_TYPE: metadata
- DICT_KEY: SPASE>Support>SupportQuantity:Other
# Index attributes
mass:
CATDESC: Log-spaced mass
- FIELDNAM: Mass (kg)
- UNITS: kg
- FORMAT: I4
- VAR_TYPE: support_data
- SCALETYP: log
- LABLAXIS: Mass (kg)
- VALIDMIN: 0
- VALIDMAX: 10
+ DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Mass
+ FIELDNAM: Mass
FILLVAL: *double_fillval
+ FORMAT: E10.4
+ LABLAXIS: Mass
LABL_PTR_1: mass_labels
- DICT_KEY: SPASE>Support>SupportQuantity:Other
+ SCALETYP: log
+ UNITS: kg
+ VALIDMAX: 1.00e-14
+ 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
- VALIDMAX: 3
+ 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: I4
- VALIDMIN: 0
- VALIDMAX: 10
+ FORMAT: E10.3
+ LABLAXIS: Impact Charge
LABL_PTR_1: spin_phase_labels
+ SCALETYP: log
UNITS: fC
- DICT_KEY: SPASE>Support>SupportQuantity:Other
-
-rectangular_lon_pixel:
- CATDESC: Longitude pixel center for IDEX SkyMap
- FIELDNAM: Rectangular Longitude Center
- 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
+ VALIDMAX: 1.00e04
+ VALIDMIN: 0.0
+ VAR_TYPE: support_data
-rectangular_lat_pixel:
- CATDESC: Latitude pixel center for IDEX SkyMap
- FIELDNAM: Rectangular Latitude Center
- 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
# 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
-
-base_charge_map: &base_charge_map
- <<: *base_charge
- DEPEND_2: rectangular_lon_pixel
- DEPEND_3: rectangular_lat_pixel
- LABL_PTR_2: rectangular_lon_pixel_label
- LABL_PTR_3: rectangular_lat_pixel_label
-
-base_mass_map: &base_mass_map
- <<: *base_mass
- DEPEND_2: rectangular_lon_pixel
- DEPEND_3: rectangular_lat_pixel
- LABL_PTR_2: rectangular_lon_pixel_label
- LABL_PTR_3: rectangular_lat_pixel_label
+ 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
-
-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
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
-
-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
- FILLVAL: *double_fillval
- DICT_KEY: SPASE>SupportQuantity:CountRate,Qualifier:Array
counts_by_charge:
<<: *base_charge
CATDESC: Count by impact charge and spin phase.
- FIELDNAM: Counts by Charge
- FORMAT: I8
- UNITS: counts
DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array
-
-counts_by_charge_map:
- <<: *base_charge_map
- CATDESC: Count by impact charge, longitude, and latitude.
- FIELDNAM: Counts by Charge Map
+ 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.
- FIELDNAM: Counts by Mass
- 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.
- FIELDNAM: Counts by Mass Map
+ 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 ebbff13742..087de061f4 100644
--- a/imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml
+++ b/imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml
@@ -1,30 +1,154 @@
-# Label attributes
-mass_labels:
- CATDESC: Labels for mass bins
- FIELDNAM: Mass Bin Labels
- VAR_TYPE: metadata
- FORMAT: A8
- DEPEND_1: mass_bins
- DICT_KEY: SPASE>Support>SupportQuantity:Other
+int_fillval: &int_fillval -9223372036854775808
+int_maxval: &int_maxval 9223372036854775807
+double_fillval: &double_fillval -1.0E31
-charge_labels:
- CATDESC: Labels for impact charge bins
- FIELDNAM: Impact Charge Bin Labels
- VAR_TYPE: metadata
- FORMAT: A8
- DEPEND_1: impact_charge_bins
- DICT_KEY: SPASE>Support>SupportQuantity:Other
+# Base attributes for charge and mass variables
+base_charge: &base_charge
+ CATDESC: " "
+ DEPEND_0: epoch
+ DEPEND_1: impact_charge
+ DEPEND_2: spin_phase
+ DISPLAY_TYPE: spectrogram
+ FIELDNAM: " "
+ FILLVAL: *int_fillval
+ FORMAT: E10.3
+ LABL_PTR_1: charge_labels
+ LABL_PTR_2: spin_phase_labels
+ VALIDMAX: *int_maxval
+ VALIDMIN: -1
+ VAR_TYPE: data
+
+base_mass: &base_mass
+ CATDESC: " "
+ DEPEND_0: epoch
+ DEPEND_1: mass
+ DEPEND_2: spin_phase
+ DISPLAY_TYPE: spectrogram
+ FIELDNAM: " "
+ FILLVAL: *int_fillval
+ FORMAT: E10.3
+ 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
+ DEPEND_2: rectangular_lon_pixel
+ DEPEND_3: rectangular_lat_pixel
+ LABL_PTR_2: rectangular_lon_pixel_label
+ LABL_PTR_3: rectangular_lat_pixel_label
+
+base_mass_map: &base_mass_map
+ <<: *base_mass
+ DEPEND_2: rectangular_lon_pixel
+ DEPEND_3: rectangular_lat_pixel
+ LABL_PTR_2: rectangular_lon_pixel_label
+ LABL_PTR_3: rectangular_lat_pixel_label
+
+# 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
\ No newline at end of file
+
+# 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
+ UNITS: degrees
+ VALIDMAX: 360
+ 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
+ UNITS: degrees
+ VALIDMAX: 90
+ VALIDMIN: -90
+ VAR_TYPE: support_data
+
+rate_by_charge_map:
+ <<: *base_charge_map
+ CATDESC: Count rate per day by impact charge, longitude, and latitude.
+ 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
+
+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
+
+rate_by_mass_map:
+ <<: *base_mass_map
+ CATDESC: Count rate per day by mass, longitude, and latitude.
+ DICT_KEY: SPASE>SupportQuantity:CountRate,Qualifier:Array
+ FIELDNAM: Rate by Mass Map
+ FILLVAL: *double_fillval
+ 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 0b52897cb3..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,45 +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: azimuth_60
- DEPEND_2: esa_step
+ 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: azimuth_6
- DEPEND_2: esa_step
+ 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
-
-
-# Re-used Coordinate
-epoch:
- <<: *default_int64
- CATDESC: Epoch Time
- DEPEND_0: epoch
- FIELDNAM: Epoch time
- Units: 'ns'
- VAR_TYPE: support_data
- LABLAXIS: Epoch
+ VAR_TYPE: data
esa_step_label:
CATDESC: ESA Steps
@@ -98,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
@@ -135,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
@@ -256,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)
@@ -272,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:
@@ -322,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
@@ -332,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
@@ -396,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
@@ -424,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
@@ -437,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
@@ -522,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 e78cbdb2ac..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,179 +1,309 @@
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_step_label:
+esa_energy_step_label:
CATDESC: ESA Steps
FIELDNAM: ESA Steps
FORMAT: A1
VAR_TYPE: metadata
-esa_step:
- VALIDMIN: 1
- VALIDMAX: 7
- FILLVAL: -9223372036854775808
+esa_energy_step:
CATDESC: Energy Step
- DEPEND_1: esa_step
FIELDNAM: Energy Step
- UNITS: ' '
FORMAT: I1
- VAR_TYPE: support_data
LABLAXIS: ESA
- LABL_PTR_1: esa_step_label
+ UNITS: " "
+ VALIDMAX: 7
+ VALIDMIN: 1
+ VAR_TYPE: support_data
-pointing_bins_label:
- CATDESC: Pointing bins
- FIELDNAM: Pointing bins
+spin_angle_label:
+ CATDESC: Spin angles
+ FIELDNAM: Spin angles
FORMAT: A4
VAR_TYPE: metadata
-pointing_bins:
+spin_angle:
+ CATDESC: Spin angle bin center in despun pointing frame
+ FIELDNAM: Spin angle
+ FORMAT: I4
+ LABLAXIS: spin angle
+ UNITS: "degrees"
+ VALIDMAX: 360
VALIDMIN: 0
- VALIDMAX: 3599
- FILLVAL: -9223372036854775808
- CATDESC: Pointing bins
- DEPEND_1: pointing_bins
- FIELDNAM: Pointing Bins
- UNITS: ' '
+ VAR_TYPE: support_data
+
+off_angle_label:
+ CATDESC: Off axis angles
+ FIELDNAM: Off axis angles
+ FORMAT: A4
+ VAR_TYPE: metadata
+
+off_angle:
+ CATDESC: Off axis angle bin center in despun pointing frame
+ FIELDNAM: Off axis angle
FORMAT: I4
+ LABLAXIS: off angle
+ UNITS: "degrees"
+ VALIDMAX: 2
+ VALIDMIN: -2
VAR_TYPE: support_data
- LABLAXIS: pointing bins
- LABL_PTR_1: pointing_bins_label
-pointing_start:
+pointing_start_met:
<<: *default
CATDESC: MET of start of pointing
FIELDNAM: Pointing start time
FORMAT: I12
+ LABLAXIS: pointing start
UNITS: s
- LABLAXIS: pointing start time
-pointing_end:
+pointing_end_met:
<<: *default
CATDESC: MET of end of pointing
FIELDNAM: Pointing end time
FORMAT: I12
+ LABLAXIS: pointing end
UNITS: s
- LABLAXIS: pointing end time
-mode:
+start_spin_number:
<<: *default
- CATDESC: Science Mode for Pointing
- FIELDNAM: Science Mode
+ CATDESC: The spin number at the start of the pointing
+ FIELDNAM: Spin number at start of pointing
FORMAT: I12
- LABLAXIS: science mode
+ LABLAXIS: Start spin
+
+end_spin_number:
+ <<: *default
+ CATDESC: The spin number at the start of the pointing
+ FIELDNAM: Spin number at the end of the pointing
+ FORMAT: I12
+ LABLAXIS: End spin
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
+ CATDESC: Science Mode for Pointing
+ DEPEND_1: esa_energy_step
+ FIELDNAM: Science Mode
+ FORMAT: I12
+ LABLAXIS: esa mode
+
+hae_longitude:
+ <<: *default
+ CATDESC: Bin longitudes in HAE coordinates
+ DEPEND_1: spin_angle
+ DEPEND_2: off_angle
+ FIELDNAM: Bin longitudes
+ FORMAT: I12
+ LABLAXIS: longitude
+ LABL_PTR_1: spin_angle_label
+ LABL_PTR_2: off_angle_label
+ UNITS: degrees
+ VALIDMAX: 360
+
+hae_latitude:
+ <<: *default
+ CATDESC: Bin latitudes in HAE coordinates
+ DEPEND_1: spin_angle
+ DEPEND_2: off_angle
+ FIELDNAM: Bin latitudes
+ FORMAT: I12
+ LABLAXIS: latitude
+ 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
+ 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
+ UNITS: "s"
triples_counts:
<<: *default
CATDESC: Counts for triple coincidence events
- DEPEND_1: pointing_bins
- DEPEND_2: esa_step
+ DEPEND_1: esa_energy_step
+ DEPEND_2: spin_angle
+ DEPEND_3: off_angle
FIELDNAM: triples coincidence counts
FORMAT: I12
- LABLAXIS: triples coincidence counts
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
-
-triples_rates:
- <<: *default
- CATDESC: Count rates for triple coincidence events
- DEPEND_1: pointing_bins
- DEPEND_2: esa_step
- FILLVAL: -1.0000000E+31
- FIELDNAM: triple coincidence count rates
- LABLAXIS: triple coincidence count rates
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
+ LABL_PTR_1: esa_energy_step_label
+ LABL_PTR_2: spin_angle_label
+ LABL_PTR_3: off_angle_label
doubles_counts:
<<: *default
- CATDESC: "Counts for double coincidence events"
- DEPEND_1: pointing_bins
- DEPEND_2: esa_step
+ CATDESC: Counts for double coincidence events
+ DEPEND_1: esa_energy_step
+ DEPEND_2: spin_angle
+ DEPEND_3: off_angle
FIELDNAM: Double coincidence counts
FORMAT: I12
- LABLAXIS: double coincidence counts
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
+ LABLAXIS: doubles
+ LABL_PTR_1: esa_energy_step_label
+ LABL_PTR_2: spin_angle_label
+ LABL_PTR_3: off_angle_label
-doubles_rates:
- <<: *default
- CATDESC: Count rates for double coincidence events
- DEPEND_1: pointing_bins
- DEPEND_2: esa_step
- FILLVAL: -1.0000000E+31
- FIELDNAM: double coincidence count rates
- LABLAXIS: double coincidence count rates
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
-
-hydrogen_counts:
+h_counts:
<<: *default
CATDESC: Counts for Hydrogen events
- DEPEND_1: pointing_bins
- DEPEND_2: esa_step
+ DEPEND_1: esa_energy_step
+ DEPEND_2: spin_angle
+ DEPEND_3: off_angle
FIELDNAM: Hydrogen counts
FORMAT: I12
- LABLAXIS: H counts
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
+ LABL_PTR_1: esa_energy_step_label
+ LABL_PTR_2: spin_angle_label
+ LABL_PTR_3: off_angle_label
-hydrogen_rates:
+h_background_rates:
<<: *default
- CATDESC: Count rates for Hydrogen events
- DEPEND_1: pointing_bins
- DEPEND_2: esa_step
- FILLVAL: -1.0000000E+31
- FIELDNAM: Hydrogen count rates
- LABLAXIS: H coincidence count rates
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
+ CATDESC: 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
-oxygen_counts:
+h_background_rates_stat_uncert:
<<: *default
- CATDESC: Count rates for Oxygen events
- DEPEND_1: pointing_bins
- DEPEND_2: esa_step
+ CATDESC: Background Hydrogen rates statistical 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
+
+h_background_rates_sys_err:
+ <<: *default
+ CATDESC: 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
+
+o_counts:
+ <<: *default
+ CATDESC: Count rates for Oxygen events
+ DEPEND_1: esa_energy_step
+ DEPEND_2: spin_angle
+ DEPEND_3: off_angle
FIELDNAM: Oxygen count rates
- LABLAXIS: O count rates
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
+ FORMAT: I12
+ LABL_PTR_1: esa_energy_step_label
+ LABL_PTR_2: spin_angle_label
+ LABL_PTR_3: off_angle_label
-oxygen_rates:
+o_background_rates:
<<: *default
- CATDESC : Count rates for Oxygen events
- DEPEND_1 : pointing_bins
- DEPEND_2 : esa_step
- FILLVAL: -1.0000000E+31
- FIELDNAM : Oxygen count rates
- LABLAXIS : O count rates
- LABL_PTR_1: pointing_bins_label
- LABL_PTR_2: esa_step_label
+ CATDESC: 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
-exposure_time:
+o_background_rates_stat_uncert:
<<: *default
- CATDESC: Exposure times by ESA step
- DEPEND_1: esa_step
- FILLVAL: -1.0000000E+31
- FIELDNAM: Exposure Times
- UNITS: "s"
- LABLAXIS: exposure times
- LABL_PTR_1: esa_step_label
+ CATDESC: Background Oxygen rates statistical 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
+
+o_background_rates_sys_err:
+ <<: *default
+ CATDESC: 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
+
+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 9bcd5dce03..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
@@ -84,6 +84,62 @@ imap_mag_l1c_norm-magi:
Logical_source: imap_mag_l1c_norm-magi
Logical_source_description: IMAP Mission MAGi Normal Rate Instrument Level-1C Data.
+imap_mag_l1d_norm-rtn:
+ <<: *default
+ Data_type: L1D_norm-rtn>Level 1D normal rate data in RTN
+ Logical_source: imap_mag_l1d_norm-rtn
+ Logical_source_description: IMAP Mission Normal Rate Instrument Level-1D Data in
+ Radial-Tangential-Normal Reference Frame.
+
+imap_mag_l1d_burst-rtn:
+ <<: *default
+ Data_type: L1D_burst-rtn>Level 1D burst rate data in RTN
+ Logical_source: imap_mag_l1d_burst-rtn
+ Logical_source_description: IMAP Mission Burst Rate Instrument Level-1D Data in
+ Radial-Tangential-Normal Reference Frame.
+
+imap_mag_l1d_norm-gse:
+ <<: *default
+ Data_type: L1D_norm-gse>Level 1D normal rate data in GSE
+ Logical_source: imap_mag_l1d_norm-gse
+ Logical_source_description: IMAP Mission Normal Rate Instrument Level-1D Data in
+ Geocentric Solar Ecliptic Reference Frame.
+
+imap_mag_l1d_burst-gse:
+ <<: *default
+ Data_type: L1D_burst-gse>Level 1D burst rate data in GSE
+ Logical_source: imap_mag_l1d_burst-gse
+ Logical_source_description: IMAP Mission Burst Rate Instrument Level-1D Data in
+ Geocentric Solar Ecliptic Reference Frame.
+
+imap_mag_l1d_norm-srf:
+ <<: *default
+ Data_type: L1D_norm-srf>Level 1D normal rate data in SRF
+ Logical_source: imap_mag_l1d_norm-srf
+ Logical_source_description: IMAP Mission Normal Rate Instrument Level-1D Data in
+ Spacecraft Reference Frame.
+
+imap_mag_l1d_burst-srf:
+ <<: *default
+ Data_type: L1D_burst-srf>Level 1D burst rate data in SRF
+ Logical_source: imap_mag_l1d_burst-srf
+ Logical_source_description: IMAP Mission Burst Rate Instrument Level-1D Data in
+ Spacecraft Reference Frame.
+
+imap_mag_l1d_norm-dsrf:
+ <<: *default
+ Data_type: L1D_norm-dsrf>Level 1D normal rate data in DSRF
+ Logical_source: imap_mag_l1d_norm-dsrf
+ Logical_source_description: IMAP Mission Normal Rate Instrument Level-1D Data in
+ Despun Spacecraft Reference Frame.
+
+imap_mag_l1d_burst-dsrf:
+ <<: *default
+ Data_type: L1D_burst-dsrf>Level 1D burst rate data in DSRF
+ Logical_source: imap_mag_l1d_burst-dsrf
+ Logical_source_description: IMAP Mission Burst Rate Instrument Level-1D Data in
+ Despun Spacecraft Reference Frame.
+
imap_mag_l2_norm-dsrf:
<<: *default
Data_type: L2_norm-dsrf>Level 2 normal rate data in DSRF
@@ -91,7 +147,6 @@ imap_mag_l2_norm-dsrf:
Logical_source_description: IMAP Mission Normal Rate Instrument Level-2 Data in
Despun Spacecraft Reference Frame.
-
imap_mag_l2_burst-dsrf:
<<: *default
Data_type: L2_burst-dsrf>Level 2 burst rate data in DSRF
@@ -111,4 +166,46 @@ imap_mag_l2_burst-srf:
Data_type: L2_burst-srf>Level 2 burst rate data in SRF
Logical_source: imap_mag_l2_burst-srf
Logical_source_description: IMAP Mission Burst Rate Instrument Level-2 Data in
- Spacecraft Reference Frame.
\ No newline at end of file
+ Spacecraft Reference Frame.
+
+imap_mag_l2_norm-rtn:
+ <<: *default
+ Data_type: L2_norm-rtn>Level 2 normal rate data in RTN
+ Logical_source: imap_mag_l2_norm-rtn
+ Logical_source_description: IMAP Mission Normal Rate Instrument Level-2 Data in
+ Radial-Tangential-Normal Reference Frame.
+
+imap_mag_l2_burst-rtn:
+ <<: *default
+ Data_type: L2_burst-rtn>Level 2 burst rate data in RTN
+ Logical_source: imap_mag_l2_burst-rtn
+ Logical_source_description: IMAP Mission Burst Rate Instrument Level-2 Data in
+ Radial-Tangential-Normal Reference Frame.
+
+imap_mag_l2_norm-gse:
+ <<: *default
+ Data_type: L2_norm-gse>Level 2 normal rate data in GSE
+ Logical_source: imap_mag_l2_norm-gse
+ Logical_source_description: IMAP Mission Normal Rate Instrument Level-2 Data in
+ Geocentric Solar Ecliptic Reference Frame.
+
+imap_mag_l2_burst-gse:
+ <<: *default
+ 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.
+
+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 c93ccdb778..40dc5f0dfa 100644
--- a/imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml
+++ b/imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml
@@ -4,27 +4,27 @@ default_attrs: &default
# Assumed values for all variable attrs unless overwritten
DEPEND_0: epoch
DISPLAY_TYPE: time_series
- FILLVAL: -9223372036854775808
+ 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,45 +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
+ FILLVAL: 255
+ FORMAT: I1
+ LABLAXIS: Generated Flag
+ UNITS: ' '
+ VALIDMAX: 1
+ VALIDMIN: 0
+
+vector_magnitude_attrs:
+ <<: *support_default
+ CATDESC: Magnitude of the magnetic field vector
+ DICT_KEY: SPASE>Field>FieldQuantity:Magnetic,Qualifier:Scalar
+ FIELDNAM: Magnetic Field Magnitude
+ FORMAT: F12.5
+ LABLAXIS: "|B|"
+ UNITS: nT
+ VALIDMAX: 9223372036854775807
+ 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
@@ -122,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
@@ -132,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 eda919f401..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,106 +426,157 @@ 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_fov:
+quality_outliers:
<<: *default_uint16
- CATDESC: Quality flag for direct event for events outside of the FOV.
- FIELDNAM: quality_fov
- LABLAXIS: quality fov
+ CATDESC: Quality flag for direct event for events outliers.
+ FIELDNAM: quality_outliers
+ LABLAXIS: quality_outliers
# TODO: come back to format
UNITS: " "
+
+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 e1ecc6c516..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,25 +1,45 @@
+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
+ DEPEND_2: pixel_index
+
latitude:
<<: *default_float32
CATDESC: Latitude bin center corresponding to healpix index with range [-90, 90].
+ DEPEND_1: pixel_index
FIELDNAM: latitude
LABLAXIS: latitude
UNITS: degrees
@@ -27,6 +47,7 @@ latitude:
longitude:
<<: *default_float32
CATDESC: Longitude bin center corresponding to healpix index with range [0, 360].
+ DEPEND_1: pixel_index
FIELDNAM: longitude
LABLAXIS: longitude
UNITS: degrees
@@ -39,29 +60,102 @@ species_bin:
# TODO: come back to format
UNITS: " "
-exposure_factor:
+dead_time_ratio:
<<: *default_float32
- CATDESC: Exposure time for a pointing.
+ CATDESC: Dead time correction ratios for each spin phase step (1ms resolution).
+ DEPEND_1: spin_phase_step
+ FIELDNAM: dead_time_ratios
+ LABLAXIS: Dead Time Ratio
+ UNITS: " "
+ VALIDMIN: 0.0
+
+sensitivity:
+ <<: *energy_dependent
+ CATDESC: Averaged instrument sensitive area.
+ FIELDNAM: sensitivity
+ LABLAXIS: sensitivity
+ # TODO: come back to format
+ UNITS: cm^2
+
+geometric_function:
+ <<: *energy_dependent
+ CATDESC: Averaged aperture area as seen by the backstop.
+ FIELDNAM: geometric_function
+ LABLAXIS: Geometric Factor
+ UNITS: cm^2
+ VALIDMIN: 0.0
+
+efficiency:
+ <<: *energy_dependent
+ CATDESC: Efficiency of the instrument in converting ENAs to valid events.
+ FIELDNAM: efficiency
+ LABLAXIS: Efficiency
+ UNITS: " "
+ 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
UNITS: seconds
-sensitivity:
- <<: *default_float32
- CATDESC: Calibration/sensitivity factor.
- FIELDNAM: sensitivity
- LABLAXIS: sensitivity
+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: counts/second
+ 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: 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
@@ -87,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.
@@ -94,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 c34038f79d..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,
@@ -36,7 +38,10 @@
import imap_processing
from imap_processing._version import __version__, __version_tuple__ # noqa: F401
-from imap_processing.ancillary.ancillary_dataset_combiner import MagAncillaryCombiner
+from imap_processing.ancillary.ancillary_dataset_combiner import (
+ GlowsAncillaryCombiner,
+ MagAncillaryCombiner,
+)
from imap_processing.cdf.utils import load_cdf, write_cdf
# TODO: change how we import things and also folder
@@ -49,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
@@ -59,7 +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.idex.idex_l2c import idex_l2c
+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
@@ -82,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__)
@@ -196,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)
@@ -258,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(
@@ -379,7 +388,7 @@ def __init__(
data_level: str,
data_descriptor: str,
dependency_str: str,
- start_date: str | None,
+ start_date: str,
repointing: str | None,
version: str,
upload_to_sdc: bool,
@@ -405,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:
@@ -620,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")
@@ -640,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
@@ -674,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: "
@@ -683,24 +673,108 @@ 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 L1A requires exactly one input science file, received: "
+ f"GLOWS L1B requires exactly one input science file, received: "
f"{science_files}."
)
input_dataset = load_cdf(science_files[0])
- datasets = [glows_l1b(input_dataset)]
+
+ # Load conversion table (needed for both hist and DE)
+ conversion_table_file = dependencies.get_processing_inputs(
+ descriptor="l1b-conversion-table-for-anc-data"
+ )[0]
+
+ 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(
+ f"{self.start_date[:4]}-{self.start_date[4:6]}-{self.start_date[6:]}"
+ )
+ day_buffer = current_day + np.timedelta64(3, "D")
+
+ 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]
+
+ # 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
@@ -708,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]:
"""
@@ -738,31 +812,148 @@ def do_processing(
elif self.data_level == "l1b":
l0_files = dependencies.get_file_paths(source="hi", descriptor="raw")
if l0_files:
- datasets = hi_l1b.hi_l1b(l0_files[0])
+ 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_files = dependencies.get_file_paths(source="hi", data_type="l1a")
- datasets = hi_l1b.hi_l1b(load_cdf(l1a_files[0]))
+ l1a_de_file = dependencies.get_file_paths(
+ source="hi", data_type="l1a", descriptor="de"
+ )[0]
+ l1b_hk_file = dependencies.get_file_paths(
+ source="hi", data_type="l1b", descriptor="hk"
+ )[0]
+ esa_energies_csv = dependencies.get_file_paths(data_type="ancillary")[0]
+ datasets = hi_l1b.annotate_direct_events(
+ 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:
@@ -796,37 +987,44 @@ def do_processing(
dependency_list = dependencies.processing_input
if self.data_level == "l1a":
- # 1 science files and 2 spice files
- if len(dependency_list) > 3:
+ # Two inputs - L0 and SPICE
+ if len(dependency_list) > 2:
raise ValueError(
f"Unexpected dependencies found for HIT L1A:"
- f"{dependency_list}. Expected only one dependency."
+ f"{dependency_list}. Expected only 2 dependencies, "
+ f"L0 and time kernels."
)
# process data to L1A products
- science_files = dependencies.get_file_paths(source="hit", descriptor="raw")
- datasets = hit_l1a(science_files[0])
+ # 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":
- data_dict = {}
- # TODO: Sean removed the file number error handling to work with the
- # new SPICE dependencies for SIT-4. Need to review and make changes
- # if needed.
l0_files = dependencies.get_file_paths(source="hit", descriptor="raw")
l1a_files = dependencies.get_file_paths(source="hit", data_type="l1a")
- if len(l0_files) > 0:
- # Add path to CCSDS file to process housekeeping
- data_dict["imap_hit_l0_raw"] = l0_files[0]
+ if len(l0_files) == 1:
+ # Path to CCSDS file to process housekeeping
+ dependency = l0_files[0]
else:
+ # 1 science file
+ if len(l1a_files) > 1:
+ raise ValueError(
+ f"Unexpected dependencies found for HIT L1B:"
+ f"{l1a_files}. Expected only one dependency."
+ )
# Add L1A dataset to process science data
- l1a_dataset = load_cdf(l1a_files[0])
- data_dict[l1a_dataset.attrs["Logical_source"]] = l1a_dataset
+ dependency = load_cdf(l1a_files[0])
# process data to L1B products
- datasets = hit_l1b(data_dict)
+ datasets = [hit_l1b(dependency, self.descriptor)]
+
elif self.data_level == "l2":
+ # 1 science files and 4 ancillary files
if len(dependency_list) != 5:
raise ValueError(
f"Unexpected dependencies found for HIT L2:"
- f"{dependency_list}. Expected only one dependency."
+ f"{dependency_list}. Expected only five dependencies."
)
# Add L1B dataset to process science data
science_files = dependencies.get_file_paths(
@@ -846,7 +1044,7 @@ def do_processing(
)
l1b_dataset = load_cdf(science_files[0])
# process data to L2 products
- datasets = hit_l2(l1b_dataset, ancillary_files)
+ datasets = [hit_l2(l1b_dataset, ancillary_files)]
return datasets
@@ -884,25 +1082,43 @@ 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) != 1:
+ if len(dependency_list) != 3:
raise ValueError(
f"Unexpected dependencies found for IDEX L2A:"
- f"{dependency_list}. Expected only one dependency."
+ f"{dependency_list}. Expected three dependencies."
)
science_files = dependencies.get_file_paths(source="idex")
dependency = load_cdf(science_files[0])
- datasets = [idex_l2a(dependency)]
+ anc_paths = dependencies.get_file_paths(data_type="ancillary")
+ ancillary_files = {}
+ for path in anc_paths:
+ ancillary_files[path.stem.split("_")[2]] = path
+ datasets = [idex_l2a(dependency, ancillary_files)]
elif self.data_level == "l2b":
if len(dependency_list) < 3 or len(dependency_list) > 4:
raise ValueError(
@@ -913,25 +1129,67 @@ 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))]
- datasets = [idex_l2b(sci_dependencies, hk_dependencies)]
- elif self.data_level == "l2c":
- if len(dependency_list) != 1:
- raise ValueError(
- f"Unexpected dependencies found for IDEX L2C:"
- f"{dependency_list}. Expected only one dependency."
- )
- sci_files = dependencies.get_file_paths(source="idex", descriptor="sci-1mo")
- dependencies = [load_cdf(f) for f in sci_files]
- datasets = [idex_l2c(dependencies)]
+ # 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
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]:
@@ -964,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
@@ -983,17 +1252,17 @@ def do_processing(
elif self.data_level == "l2":
data_dict = {}
- # TODO: Add ancillary descriptors when maps using them are
- # implemented.
- anc_dependencies = dependencies.get_file_paths(
- source="lo",
- )
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)
+ datasets = lo_l2.lo_l2(data_dict, anc_dependencies, self.descriptor)
return datasets
@@ -1073,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:"
@@ -1148,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."""
@@ -1174,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:
@@ -1184,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):
@@ -1246,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(
@@ -1303,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.
@@ -1381,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 = {
@@ -1407,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}
@@ -1415,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.
@@ -1435,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 21e727ea93..794c09730d 100644
--- a/imap_processing/codice/codice_l1a.py
+++ b/imap_processing/codice/codice_l1a.py
@@ -1,1563 +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:
- """
- Contains methods for processing L0 data and creating L1a data products.
-
- 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.
-
- Methods
- -------
- 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 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
- ):
- # 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:
- """
- Create ``xr.DataArrays`` for the coords needed in the final dataset.
-
- The coordinates for the dataset depend on the data product being made.
- """
- 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),
- )
- self.coords[name] = coord
-
- # Define the values for the coordinates
- for name in coord_names:
- if name in [
- "esa_step",
- "inst_az",
- "spin_sector",
- "spin_sector_pairs",
- "spin_sector_index",
- "ssd_index",
- ]:
- 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 [
- "spin_sector_label",
- "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]
-
- coord = xr.DataArray(
- values,
- name=name,
- dims=dims,
- attrs=self.cdf_attrs.get_variable_attributes(name, check_schema=False),
- )
-
- 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"]
- ):
- # 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,
- )
-
- # 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 = 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}_delta"] = xr.DataArray(
- deltas,
- dims=[f"{energy_bin_name}_delta"],
- attrs=self.cdf_attrs.get_variable_attributes(
- f"{self.config['dataset_name'].split('_')[-1]}-{energy_bin_name}_delta",
- 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,
- )
-
- 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]]:
- """
- 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 : NDArray[float]
- An array whose values represent the deltas of the energy bins.
- """
- data_product = self.config["dataset_name"].split("-")[-1].upper()
- energy_table = getattr(constants, f"{data_product}_ENERGY_TABLE")[species]
-
- # Find the centers and deltas of the energy bins
- centers = np.array(
- [
- (energy_table[i] + energy_table[i + 1]) / 2
- for i in range(len(energy_table) - 1)
- ]
- )
- deltas = energy_table[1:] - centers
-
- return centers, deltas
- 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
- )
-
- # 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)
-
- # 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]]:
+def process_l1a( # noqa: PLR0912
+ dependency: ProcessingInputCollection,
+) -> list[xr.Dataset]:
"""
- 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.
+ Process L1A data based on descriptor and dependencies.
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``).
+ dependency : ProcessingInputCollection
+ Collection of processing inputs required for L1A processing.
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"
+ 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:
- 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]])
- )
- 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),
- )
+ xtce_file = path / "imap_codice_packet-definition_20250101_v001.xml"
- # 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,
+ datasets_by_apid = packet_file_to_datasets(
+ science_file,
+ xtce_file,
)
-
- # 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 ["NumEvents", "DataQuality"]:
- dims = ["epoch"]
- else:
- dims = ["epoch", "event_num"]
- dataset[variable_name] = xr.DataArray(
- np.array(data[variable_name]),
- name=variable_name,
- dims=dims,
- attrs=attrs,
+ 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)
)
-
- 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],
+ elif apid == CODICEAPID.COD_HI_OMNI_SPECIES_COUNTS:
+ datasets.append(
+ process_by_table_id(datasets_by_apid[apid], lut_file, l1a_hi_omni)
)
- 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"],
+ 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)
)
- pipeline.dataset["acq_start_subseconds"] = (
- "_",
- metadata_values["ACQ_START_SUBSECONDS"],
+ 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)
)
-
- 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_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)
+ )
+ 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
)
-
- # 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"],
+ )
+ 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
)
- data[f"P{priority_num}_NumEvents"] = np.full(num_epochs, 65535, dtype=np.uint16)
- data[f"P{priority_num}_DataQuality"] = 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}_NumEvents"][epoch_index] = num_events
- data[f"P{priority_num}_DataQuality"][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_AGGREGATED:
+ logger.info("Processing Lo Counters aggregated")
+ datasets.append(
+ process_by_table_id(
+ datasets_by_apid[apid], lut_file, l1a_lo_counters_aggregated
)
-
- 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_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
+ )
+ )
+ 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 0482119cd5..0a7998ee91 100644
--- a/imap_processing/codice/codice_l2.py
+++ b/imap_processing/codice/codice_l2.py
@@ -9,63 +9,1456 @@
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]:
"""
- Will process CoDICE l1 data to create l2 data products.
+ Get the LO DE lookup tables for energy conversions.
Parameters
----------
- file_path : pathlib.Path
- Path to the CoDICE L1 file to process.
+ dependencies : ProcessingInputCollection
+ The collection of processing input files.
Returns
-------
- l2_dataset : xarray.Dataset
- The``xarray`` dataset containing the science data and supporting metadata.
+ 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:
"""
- logger.info(f"Processing {file_path}")
+ 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.
- # Open the l1 file
- l1_dataset = load_cdf(file_path)
+ The formula for omni-directional intensities is::
- # 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")
+ l1b species data / (geometric_factor * efficiency * energy_passband)
- # Use the L1 data product as a starting point for L2
- l2_dataset = l1_dataset.copy()
+ 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
- # Get the L2 CDF attributes
+ 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")
+ 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"),
+ )
- # Update the global attributes
- l2_dataset.attrs = cdf_attrs.get_global_attributes(dataset_name)
+ l1b_dataset["epoch"].attrs["DELTA_MINUS_VAR"] = "epoch_delta_minus"
+ l1b_dataset["epoch"].attrs["DELTA_PLUS_VAR"] = "epoch_delta_plus"
- # Set the variable attributes
- for variable_name in l2_dataset:
- l2_dataset[variable_name].attrs = cdf_attrs.get_variable_attributes(
- variable_name, check_schema=False
+ 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
+ ----------
+ 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.
+ """
+ # 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")
+
+ l2_dataset = load_cdf(file_path).copy()
+
+ geometric_factor_lookup = get_geometric_factor_lut(dependencies)
+ efficiency_lookup = get_efficiency_lut(dependencies)
+
+ 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",
+ "imap_codice_l2_hi-counters-aggregated",
+ "imap_codice_l2_lo-counters-singles",
+ "imap_codice_l2_lo-counters-aggregated",
+ "imap_codice_l2_lo-sw-priority",
+ "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":
+ # Convert the following data variables to physical units using
+ # calibration data:
+ # - ssd_energy
+ # - tof
+ # - elevation_angle
+ # - spin_angle
+ # 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
+ 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.
+ 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
+ l2_dataset = process_hi_omni(dependencies)
+
+ elif dataset_name == "imap_codice_l2_lo-direct-events":
+ # Convert the following data variables to physical units using
+ # calibration data:
+ # - apd_energy
+ # - elevation_angle
+ # - tof
+ # - spin_sector
+ # - esa_step
+ # 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
+ l2_dataset = process_lo_direct_events(dependencies)
- # TODO: Add L2-specific algorithms/functionality here. For SIT-4, we can
- # just keep the data as-is.
+ # 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")
diff --git a/imap_processing/codice/constants.py b/imap_processing/codice/constants.py
index ebbf3732a6..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,609 +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 = [
- "NumEvents",
- "DataQuality",
- "SSDEnergy",
- "TOF",
- "SSD_ID",
- "ERGE",
- "MultiFlag",
- "Type",
- "SpinAngle",
- "SpinNumber",
-]
-HI_DE_VARIABLE_NAMES = [f"P{n}_{field}" for n in range(6) for field in HI_DE_CDF_FIELDS]
-LO_DE_CDF_FIELDS = [
- "NumEvents",
- "DataQuality",
- "APDGain",
- "APD_ID",
- "APDEnergy",
- "TOF",
- "MultiFlag",
- "PHAType",
- "SpinAngle",
- "EnergyStep",
-]
-LO_DE_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,
- "TOFPlusAPD": False,
- "TOFOnly": False,
- "PositionPlusAPD": False,
- "PositionOnly": False,
- "STAorSTBPlusAPD": False,
- "STAorSTBOnly": False,
- "Reserved1": False,
- "Reserved2": False,
- "SPOnly": False,
- "APDOnly": False,
- "LowTOFCutoff": False,
- "STA": True,
- "STB": True,
- "SP": True,
- "TotalPositionCount": True,
- "InvalidPositionCount": False,
- "ASIC1FlagInvalid": False,
- "ASIC2FlagInvalid": False,
- "ASIC1ChannelInvalid": False,
- "ASIC2ChannelInvalid": False,
- "TEC4TimeoutTOFNoPos": False,
- "TEC4TimeoutPosNoTOF": False,
- "TEC4TimeoutNoPosTOF": False,
- "TEC5TimeoutTOFNoPos": False,
- "TEC5TimeoutPosNoTOF": False,
- "TEC5TimeoutNoPosTOF": 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,
- "LowTOFCutoff": False,
- "Reserved6": False,
- "Reserved7": False,
- "ASIC1FlagInvalid": True,
- "ASIC2FlagInvalid": True,
- "ASIC1ChannelInvalid": False,
- "ASIC2ChannelInvalid": False,
-}
-HI_COUNTERS_AGGREGATED_VARIABLE_NAMES = [
- name
- for name, is_active in HI_COUNTERS_AGGREGATED_ACTIVE_VARIABLES.items()
- if is_active
-]
-
-# 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,
+HI_IALIRT_ELEVATION_ANGLE = np.array(
+ [
+ 132.8,
+ 65.7,
+ 47.1,
+ 114.3,
],
- "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,
+ dtype=np.float32,
+)
+HI_IALIRT_REF_SPIN_ANGLE = np.array(
+ [
+ 286.85,
+ 264.55,
+ 343.16,
+ 5.44,
],
- "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,
- ],
- "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],
-}
+ dtype=float,
+)
-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,
- },
-}
-
-# 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
@@ -720,271 +124,120 @@
CODICEAPID.COD_HI_PHA: {
"num_priorities": 6,
"bit_structure": {
- "SSDEnergy": {
+ "ssd_energy": {
"bit_length": 11,
"dtype": np.uint16,
"fillval": np.iinfo(np.uint16).max,
},
- "TOF": {
+ "tof": {
"bit_length": 10,
"dtype": np.uint16,
"fillval": np.iinfo(np.uint16).max,
},
- "SSD_ID": {
+ "ssd_id": {
"bit_length": 4,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "ERGE": {
+ "gain": {
"bit_length": 2,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "MultiFlag": {
+ "multi_flag": {
"bit_length": 1,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "Type": {
+ "type": {
"bit_length": 2,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "SpinAngle": {
+ "spin_sector": {
"bit_length": 5,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "SpinNumber": {
+ "spin_number": {
"bit_length": 4,
"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,
"bit_structure": {
- "APDGain": {
+ "gain": {
"bit_length": 1,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "APD_ID": {
+ "apd_id": {
"bit_length": 5,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "Position": {
+ "position": {
"bit_length": 5,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "APDEnergy": {
+ "apd_energy": {
"bit_length": 9,
"dtype": np.uint16,
"fillval": np.iinfo(np.uint16).max,
},
- "TOF": {
+ "tof": {
"bit_length": 10,
"dtype": np.uint16,
"fillval": np.iinfo(np.uint16).max,
},
- "MultiFlag": {
+ "multi_flag": {
"bit_length": 1,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "PHAType": {
+ "type": {
"bit_length": 2,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "SpinAngle": {
+ "spin_sector": {
"bit_length": 5,
"dtype": np.uint8,
"fillval": np.iinfo(np.uint8).max,
},
- "EnergyStep": {
+ "energy_step": {
"bit_length": 7,
"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
@@ -1508,529 +761,257 @@
255: 2151415807,
}
-# 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.7083,
- 578.7083,
- 578.7083,
- 578.7083,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- ],
- 1: [
- 578.7083,
- 578.7083,
- 578.7083,
- 578.7083,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- ],
- 2: [
- 578.7083,
- 578.7083,
- 578.7083,
- 578.7083,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- ],
- 3: [
- 578.7083,
- 578.7083,
- 578.7083,
- 578.7083,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 289.35416,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 192.90277,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 144.67708,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 115.74167,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
- 95.69444,
+# ------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,
+ },
+}
+
+# ------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 de36f1ec72..0000000000
--- a/imap_processing/decom.py
+++ /dev/null
@@ -1,39 +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 typing import Union
-
-from space_packet_parser import definitions
-
-
-def decom_packets(
- packet_file: Union[str, Path], xtce_packet_definition: Union[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 7ef826c589..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, ...]]:
"""
@@ -412,6 +439,7 @@ def __init__(
for dim, constructed_bins in zip(
[CoordNames.AZIMUTH_L1C.value, CoordNames.ELEVATION_L1C.value],
[self.sky_grid.az_bin_midpoints, self.sky_grid.el_bin_midpoints],
+ strict=False,
):
if not np.allclose(
sorted(constructed_bins),
@@ -429,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],
)
@@ -522,6 +551,7 @@ def __init__(
for dim, constructed_bins in zip(
[CoordNames.AZIMUTH_L1C.value, CoordNames.ELEVATION_L1C.value],
[azimuth_pixel_center, elevation_pixel_center],
+ strict=False,
):
if not np.allclose(
self.data[dim],
@@ -538,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:
@@ -583,44 +616,166 @@ def __repr__(self) -> str:
f"num_points={self.num_points})"
)
+ def downsample_counts(self) -> None:
+ """
+ Downsample the counts variable to match the pset nside.
+
+ 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 HiPointingSet(PointingSet):
+class LoHiBasePointingSet(PointingSet):
"""
- PointingSet object specific to Hi L1C PSet data.
+ Base class for Lo and Hi pointing sets with HAE coordinate data.
- Parameters
- ----------
- dataset : xarray.Dataset
- Hi L1C pointing set data loaded in an xarray.DataArray.
+ This class provides common functionality for pointing sets that contain
+ hae_longitude and hae_latitude coordinates in the dataset.
"""
- def __init__(self, dataset: xr.Dataset):
- super().__init__(dataset, spice_reference_frame=geometry.SpiceFrame.ECLIPJ2000)
+ tiling_type: SkyTilingType = SkyTilingType.RECTANGULAR
- # 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",
- }
- )
+ def update_az_el_points(self) -> None:
+ """
+ Update the az_el_points instance variable with new az/el coordinates.
- # 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]
+ 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})
)
- self.az_el_points = np.column_stack(
- (
- np.squeeze(self.data["hae_longitude"]),
- np.squeeze(self.data["hae_latitude"]),
- )
+ # 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.
+
+ Parameters
+ ----------
+ dataset : xarray.Dataset | str | Path
+ Hi L1C pointing set data loaded in a xarray.DataArray.
+ """
+
+ # 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",
+ }
+
+ def __init__(self, dataset: xr.Dataset | str | Path):
+ super().__init__(dataset, spice_reference_frame=geometry.SpiceFrame.IMAP_HAE)
+
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.
@@ -631,29 +786,27 @@ class LoPointingSet(PointingSet):
"""
def __init__(self, dataset: xr.Dataset):
- super().__init__(dataset, spice_reference_frame=geometry.SpiceFrame.IMAP_DPS)
- # TODO: Use spatial_utils.az_el_grid instead of
- # manually creating the lon/lat values
- inferred_spacing_deg = 360 / dataset.longitude.size
- longitude_bin_centers = np.arange(
- 0 + inferred_spacing_deg / 2, 360, inferred_spacing_deg
- )
- latitude_bin_centers = np.arange(
- -2 + inferred_spacing_deg / 2, 2, inferred_spacing_deg
- )
+ super().__init__(dataset, spice_reference_frame=geometry.SpiceFrame.IMAP_HAE)
- # Could be wrong about the order here
- longitude_grid, latitude_grid = np.meshgrid(
- longitude_bin_centers,
- latitude_bin_centers,
- indexing="ij",
- )
+ self.spatial_coords = ("spin_angle", "off_angle")
- longitude = longitude_grid.ravel()
- latitude = latitude_grid.ravel()
+ # Update az_el_points using the base class method
+ self.update_az_el_points()
- self.az_el_points = np.column_stack((longitude, latitude))
- self.spatial_coords = ("longitude", "latitude")
+ @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
@@ -687,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
@@ -756,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.
@@ -782,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
------
@@ -790,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
@@ -814,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:
@@ -849,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)
@@ -1095,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(
@@ -1162,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
@@ -1189,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.
@@ -1206,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
-------
@@ -1227,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]})
@@ -1241,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)
@@ -1254,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()
@@ -1290,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,
@@ -1308,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
@@ -1405,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(
@@ -1537,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))
@@ -1573,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}: "
@@ -1741,14 +1963,14 @@ 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
# into two lists, then convert both to numpy arrays
# and move the pixel dim to the last dim of values
interpolated_data_by_rect_pixel, subdiv_depth_of_value_by_pixel = zip(
- *best_value_and_recursion_depth_by_pixel
+ *best_value_and_recursion_depth_by_pixel, strict=False
)
interpolated_data_by_rect_pixel = np.moveaxis(
np.array(interpolated_data_by_rect_pixel), 0, -1
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 6a38254a21..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",]
+_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,10 +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.ECLIPJ2000
- 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_exclusions-by-instr-team_20250923_v002.dat b/imap_processing/glows/ancillary/imap_glows_exclusions-by-instr-team_20250923_v002.dat
new file mode 100644
index 0000000000..50faa6d966
--- /dev/null
+++ b/imap_processing/glows/ancillary/imap_glows_exclusions-by-instr-team_20250923_v002.dat
@@ -0,0 +1,10 @@
+# Description: list of exclusions for L1b defined by IMAP/GLOWS Instrument Team for ground-processing pipeline in the IMAP SDC
+# Value 1 in mask_array means that a given bin is to be excluded
+# version: 0.2
+# columns: l1b_unique_block_identifier, histogram_mask_array
+2013-09-08T09:20:14 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2013-09-08T09:22:14 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2014-09-08T15:01:01 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2014-09-08T15:03:01 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2015-06-06T23:18:00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2015-06-06T23:20:00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
diff --git a/imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat b/imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat
new file mode 100644
index 0000000000..567242aa67
--- /dev/null
+++ b/imap_processing/glows/ancillary/imap_glows_map-of-excluded-regions_20250923_v002.dat
@@ -0,0 +1,393 @@
+# Description: map of excluded regions provided by IMAP/GLOWS Instrument Team for ground-processing pipeline at IMAP SDC
+# generated by script: generate_map_of_excluded_regions.py
+# version: 0.2
+# columns: ecliptic_longitude_deg, ecliptic_latitude_deg
+8.437499999999998579e+01 2.074237995448714500e+01
+8.718749999999998579e+01 2.074237995448714500e+01
+9.000000000000000000e+01 2.074237995448714500e+01
+9.281250000000000000e+01 2.074237995448714500e+01
+9.562500000000000000e+01 2.074237995448714500e+01
+9.843750000000000000e+01 2.074237995448714500e+01
+1.012499999999999858e+02 2.074237995448714500e+01
+1.040625000000000000e+02 2.074237995448714500e+01
+1.068750000000000000e+02 2.074237995448714500e+01
+1.096875000000000000e+02 2.074237995448714500e+01
+1.124999999999999858e+02 2.074237995448714500e+01
+1.153124999999999716e+02 2.074237995448714500e+01
+1.181250000000000000e+02 2.074237995448714500e+01
+1.209375000000000000e+02 2.074237995448714500e+01
+1.237499999999999858e+02 2.074237995448714500e+01
+1.265625000000000000e+02 2.074237995448714500e+01
+1.293750000000000000e+02 2.074237995448714500e+01
+1.321875000000000000e+02 2.074237995448714500e+01
+1.350000000000000000e+02 2.074237995448714500e+01
+1.378125000000000000e+02 2.074237995448714500e+01
+1.406249999999999716e+02 2.074237995448714500e+01
+1.434374999999999716e+02 2.074237995448714500e+01
+1.462500000000000000e+02 2.074237995448714500e+01
+1.490625000000000000e+02 2.074237995448714500e+01
+1.518750000000000000e+02 2.074237995448714500e+01
+1.546875000000000000e+02 2.074237995448714500e+01
+1.575000000000000000e+02 2.074237995448714500e+01
+1.603125000000000000e+02 2.074237995448714500e+01
+1.631249999999999716e+02 2.074237995448714500e+01
+1.659375000000000000e+02 2.074237995448714500e+01
+1.687499999999999716e+02 2.074237995448714500e+01
+1.715624999999999716e+02 2.074237995448714500e+01
+1.743749999999999716e+02 2.074237995448714500e+01
+1.771875000000000000e+02 2.074237995448714500e+01
+1.800000000000000000e+02 2.074237995448714500e+01
+1.828125000000000000e+02 2.074237995448714500e+01
+1.856250000000000000e+02 2.074237995448714500e+01
+1.884375000000000000e+02 2.074237995448714500e+01
+1.912500000000000000e+02 2.074237995448714500e+01
+1.940624999999999716e+02 2.074237995448714500e+01
+1.968750000000000000e+02 2.074237995448714500e+01
+1.996874999999999716e+02 2.074237995448714500e+01
+2.024999999999999716e+02 2.074237995448714500e+01
+2.053124999999999716e+02 2.074237995448714500e+01
+2.081250000000000000e+02 2.074237995448714500e+01
+2.109375000000000000e+02 2.074237995448714500e+01
+2.137500000000000000e+02 2.074237995448714500e+01
+2.165625000000000000e+02 2.074237995448714500e+01
+2.193750000000000000e+02 2.074237995448714500e+01
+2.221875000000000000e+02 2.074237995448714500e+01
+2.249999999999999716e+02 2.074237995448714500e+01
+2.278125000000000000e+02 2.074237995448714500e+01
+2.306249999999999432e+02 2.074237995448714500e+01
+2.334375000000000284e+02 2.074237995448714500e+01
+2.362500000000000000e+02 2.074237995448714500e+01
+2.390625000000000000e+02 2.074237995448714500e+01
+8.578124999999998579e+01 2.202431283704216725e+01
+8.859375000000000000e+01 2.202431283704216725e+01
+9.140625000000000000e+01 2.202431283704216725e+01
+9.421875000000000000e+01 2.202431283704216725e+01
+9.703124999999998579e+01 2.202431283704216725e+01
+9.984374999999998579e+01 2.202431283704216725e+01
+1.026562499999999858e+02 2.202431283704216725e+01
+1.054687500000000000e+02 2.202431283704216725e+01
+1.082812500000000000e+02 2.202431283704216725e+01
+1.110937500000000000e+02 2.202431283704216725e+01
+1.139062500000000000e+02 2.202431283704216725e+01
+1.167187500000000142e+02 2.202431283704216725e+01
+1.195312500000000000e+02 2.202431283704216725e+01
+1.223437499999999858e+02 2.202431283704216725e+01
+1.251562499999999858e+02 2.202431283704216725e+01
+1.279687499999999716e+02 2.202431283704216725e+01
+1.307812499999999716e+02 2.202431283704216725e+01
+1.335937500000000000e+02 2.202431283704216725e+01
+1.364062500000000000e+02 2.202431283704216725e+01
+1.392187500000000000e+02 2.202431283704216725e+01
+1.420312500000000000e+02 2.202431283704216725e+01
+1.448437500000000000e+02 2.202431283704216725e+01
+1.476562500000000000e+02 2.202431283704216725e+01
+1.504687500000000000e+02 2.202431283704216725e+01
+1.532812499999999716e+02 2.202431283704216725e+01
+1.560937499999999716e+02 2.202431283704216725e+01
+1.589062499999999716e+02 2.202431283704216725e+01
+1.617187500000000000e+02 2.202431283704216725e+01
+1.645312500000000000e+02 2.202431283704216725e+01
+1.673437500000000000e+02 2.202431283704216725e+01
+1.701562500000000000e+02 2.202431283704216725e+01
+1.729687500000000000e+02 2.202431283704216725e+01
+1.757812500000000000e+02 2.202431283704216725e+01
+1.785937499999999716e+02 2.202431283704216725e+01
+1.814062500000000000e+02 2.202431283704216725e+01
+1.842187499999999716e+02 2.202431283704216725e+01
+1.870312499999999716e+02 2.202431283704216725e+01
+1.898437499999999716e+02 2.202431283704216725e+01
+1.926562500000000000e+02 2.202431283704216725e+01
+1.954687500000000000e+02 2.202431283704216725e+01
+1.982812500000000000e+02 2.202431283704216725e+01
+2.010937500000000000e+02 2.202431283704216725e+01
+2.039062500000000000e+02 2.202431283704216725e+01
+2.067187500000000000e+02 2.202431283704216725e+01
+2.095312499999999716e+02 2.202431283704216725e+01
+2.123437500000000000e+02 2.202431283704216725e+01
+2.151562499999999716e+02 2.202431283704216725e+01
+2.179687499999999716e+02 2.202431283704216725e+01
+2.207812499999999716e+02 2.202431283704216725e+01
+2.235937500000000000e+02 2.202431283704216725e+01
+2.264062500000000000e+02 2.202431283704216725e+01
+2.292187499999999716e+02 2.202431283704216725e+01
+2.320312499999999716e+02 2.202431283704216725e+01
+2.348437499999999716e+02 2.202431283704216725e+01
+2.376562500000000000e+02 2.202431283704216725e+01
+8.437499999999998579e+01 2.331795706533424095e+01
+8.718749999999998579e+01 2.331795706533424095e+01
+9.000000000000000000e+01 2.331795706533424095e+01
+9.281250000000000000e+01 2.331795706533424095e+01
+9.562500000000000000e+01 2.331795706533424095e+01
+9.843750000000000000e+01 2.331795706533424095e+01
+1.012499999999999858e+02 2.331795706533424095e+01
+1.040625000000000000e+02 2.331795706533424095e+01
+1.068750000000000000e+02 2.331795706533424095e+01
+1.096875000000000000e+02 2.331795706533424095e+01
+1.124999999999999858e+02 2.331795706533424095e+01
+1.153124999999999716e+02 2.331795706533424095e+01
+1.181250000000000000e+02 2.331795706533424095e+01
+1.209375000000000000e+02 2.331795706533424095e+01
+1.237499999999999858e+02 2.331795706533424095e+01
+1.265625000000000000e+02 2.331795706533424095e+01
+1.293750000000000000e+02 2.331795706533424095e+01
+1.321875000000000000e+02 2.331795706533424095e+01
+1.350000000000000000e+02 2.331795706533424095e+01
+1.378125000000000000e+02 2.331795706533424095e+01
+1.406249999999999716e+02 2.331795706533424095e+01
+1.434374999999999716e+02 2.331795706533424095e+01
+1.462500000000000000e+02 2.331795706533424095e+01
+1.490625000000000000e+02 2.331795706533424095e+01
+1.518750000000000000e+02 2.331795706533424095e+01
+1.546875000000000000e+02 2.331795706533424095e+01
+1.575000000000000000e+02 2.331795706533424095e+01
+1.603125000000000000e+02 2.331795706533424095e+01
+1.631249999999999716e+02 2.331795706533424095e+01
+1.659375000000000000e+02 2.331795706533424095e+01
+1.687499999999999716e+02 2.331795706533424095e+01
+1.715624999999999716e+02 2.331795706533424095e+01
+1.743749999999999716e+02 2.331795706533424095e+01
+1.771875000000000000e+02 2.331795706533424095e+01
+1.800000000000000000e+02 2.331795706533424095e+01
+1.828125000000000000e+02 2.331795706533424095e+01
+1.856250000000000000e+02 2.331795706533424095e+01
+1.884375000000000000e+02 2.331795706533424095e+01
+1.912500000000000000e+02 2.331795706533424095e+01
+1.940624999999999716e+02 2.331795706533424095e+01
+1.968750000000000000e+02 2.331795706533424095e+01
+1.996874999999999716e+02 2.331795706533424095e+01
+2.024999999999999716e+02 2.331795706533424095e+01
+2.053124999999999716e+02 2.331795706533424095e+01
+2.081250000000000000e+02 2.331795706533424095e+01
+2.109375000000000000e+02 2.331795706533424095e+01
+2.137500000000000000e+02 2.331795706533424095e+01
+2.165625000000000000e+02 2.331795706533424095e+01
+2.193750000000000000e+02 2.331795706533424095e+01
+2.221875000000000000e+02 2.331795706533424095e+01
+2.249999999999999716e+02 2.331795706533424095e+01
+2.278125000000000000e+02 2.331795706533424095e+01
+2.306249999999999432e+02 2.331795706533424095e+01
+2.334375000000000284e+02 2.331795706533424095e+01
+2.362500000000000000e+02 2.331795706533424095e+01
+2.390625000000000000e+02 2.331795706533424095e+01
+8.578124999999998579e+01 2.462431835216408871e+01
+8.859375000000000000e+01 2.462431835216408871e+01
+9.140625000000000000e+01 2.462431835216408871e+01
+9.421875000000000000e+01 2.462431835216408871e+01
+9.703124999999998579e+01 2.462431835216408871e+01
+9.984374999999998579e+01 2.462431835216408871e+01
+1.026562499999999858e+02 2.462431835216408871e+01
+1.054687500000000000e+02 2.462431835216408871e+01
+1.082812500000000000e+02 2.462431835216408871e+01
+1.110937500000000000e+02 2.462431835216408871e+01
+1.139062500000000000e+02 2.462431835216408871e+01
+1.167187500000000142e+02 2.462431835216408871e+01
+1.195312500000000000e+02 2.462431835216408871e+01
+1.223437499999999858e+02 2.462431835216408871e+01
+1.251562499999999858e+02 2.462431835216408871e+01
+1.279687499999999716e+02 2.462431835216408871e+01
+1.307812499999999716e+02 2.462431835216408871e+01
+1.335937500000000000e+02 2.462431835216408871e+01
+1.364062500000000000e+02 2.462431835216408871e+01
+1.392187500000000000e+02 2.462431835216408871e+01
+1.420312500000000000e+02 2.462431835216408871e+01
+1.448437500000000000e+02 2.462431835216408871e+01
+1.476562500000000000e+02 2.462431835216408871e+01
+1.504687500000000000e+02 2.462431835216408871e+01
+1.532812499999999716e+02 2.462431835216408871e+01
+1.560937499999999716e+02 2.462431835216408871e+01
+1.589062499999999716e+02 2.462431835216408871e+01
+1.617187500000000000e+02 2.462431835216408871e+01
+1.645312500000000000e+02 2.462431835216408871e+01
+1.673437500000000000e+02 2.462431835216408871e+01
+1.701562500000000000e+02 2.462431835216408871e+01
+1.729687500000000000e+02 2.462431835216408871e+01
+1.757812500000000000e+02 2.462431835216408871e+01
+1.785937499999999716e+02 2.462431835216408871e+01
+1.814062500000000000e+02 2.462431835216408871e+01
+1.842187499999999716e+02 2.462431835216408871e+01
+1.870312499999999716e+02 2.462431835216408871e+01
+1.898437499999999716e+02 2.462431835216408871e+01
+1.926562500000000000e+02 2.462431835216408871e+01
+1.954687500000000000e+02 2.462431835216408871e+01
+1.982812500000000000e+02 2.462431835216408871e+01
+2.010937500000000000e+02 2.462431835216408871e+01
+2.039062500000000000e+02 2.462431835216408871e+01
+2.067187500000000000e+02 2.462431835216408871e+01
+2.095312499999999716e+02 2.462431835216408871e+01
+2.123437500000000000e+02 2.462431835216408871e+01
+2.151562499999999716e+02 2.462431835216408871e+01
+2.179687499999999716e+02 2.462431835216408871e+01
+2.207812499999999716e+02 2.462431835216408871e+01
+2.235937500000000000e+02 2.462431835216408871e+01
+2.264062500000000000e+02 2.462431835216408871e+01
+2.292187499999999716e+02 2.462431835216408871e+01
+2.320312499999999716e+02 2.462431835216408871e+01
+2.348437499999999716e+02 2.462431835216408871e+01
+2.376562500000000000e+02 2.462431835216408871e+01
+8.437499999999998579e+01 2.594447977237001268e+01
+8.718749999999998579e+01 2.594447977237001268e+01
+9.000000000000000000e+01 2.594447977237001268e+01
+9.281250000000000000e+01 2.594447977237001268e+01
+9.562500000000000000e+01 2.594447977237001268e+01
+9.843750000000000000e+01 2.594447977237001268e+01
+1.012499999999999858e+02 2.594447977237001268e+01
+1.040625000000000000e+02 2.594447977237001268e+01
+1.068750000000000000e+02 2.594447977237001268e+01
+1.096875000000000000e+02 2.594447977237001268e+01
+1.124999999999999858e+02 2.594447977237001268e+01
+1.153124999999999716e+02 2.594447977237001268e+01
+1.181250000000000000e+02 2.594447977237001268e+01
+1.209375000000000000e+02 2.594447977237001268e+01
+1.237499999999999858e+02 2.594447977237001268e+01
+1.265625000000000000e+02 2.594447977237001268e+01
+1.293750000000000000e+02 2.594447977237001268e+01
+1.321875000000000000e+02 2.594447977237001268e+01
+1.350000000000000000e+02 2.594447977237001268e+01
+1.378125000000000000e+02 2.594447977237001268e+01
+1.406249999999999716e+02 2.594447977237001268e+01
+1.434374999999999716e+02 2.594447977237001268e+01
+1.462500000000000000e+02 2.594447977237001268e+01
+1.490625000000000000e+02 2.594447977237001268e+01
+1.518750000000000000e+02 2.594447977237001268e+01
+1.546875000000000000e+02 2.594447977237001268e+01
+1.575000000000000000e+02 2.594447977237001268e+01
+1.603125000000000000e+02 2.594447977237001268e+01
+1.631249999999999716e+02 2.594447977237001268e+01
+1.659375000000000000e+02 2.594447977237001268e+01
+1.687499999999999716e+02 2.594447977237001268e+01
+1.715624999999999716e+02 2.594447977237001268e+01
+1.743749999999999716e+02 2.594447977237001268e+01
+1.771875000000000000e+02 2.594447977237001268e+01
+1.800000000000000000e+02 2.594447977237001268e+01
+1.828125000000000000e+02 2.594447977237001268e+01
+1.856250000000000000e+02 2.594447977237001268e+01
+1.884375000000000000e+02 2.594447977237001268e+01
+1.912500000000000000e+02 2.594447977237001268e+01
+1.940624999999999716e+02 2.594447977237001268e+01
+1.968750000000000000e+02 2.594447977237001268e+01
+1.996874999999999716e+02 2.594447977237001268e+01
+2.024999999999999716e+02 2.594447977237001268e+01
+2.053124999999999716e+02 2.594447977237001268e+01
+2.081250000000000000e+02 2.594447977237001268e+01
+2.109375000000000000e+02 2.594447977237001268e+01
+2.137500000000000000e+02 2.594447977237001268e+01
+2.165625000000000000e+02 2.594447977237001268e+01
+2.193750000000000000e+02 2.594447977237001268e+01
+2.221875000000000000e+02 2.594447977237001268e+01
+2.249999999999999716e+02 2.594447977237001268e+01
+2.278125000000000000e+02 2.594447977237001268e+01
+2.306249999999999432e+02 2.594447977237001268e+01
+2.334375000000000284e+02 2.594447977237001268e+01
+2.362500000000000000e+02 2.594447977237001268e+01
+2.390625000000000000e+02 2.594447977237001268e+01
+8.578124999999998579e+01 2.727961273597808756e+01
+8.859375000000000000e+01 2.727961273597808756e+01
+9.140625000000000000e+01 2.727961273597808756e+01
+9.421875000000000000e+01 2.727961273597808756e+01
+9.703124999999998579e+01 2.727961273597808756e+01
+9.984374999999998579e+01 2.727961273597808756e+01
+1.026562499999999858e+02 2.727961273597808756e+01
+1.054687500000000000e+02 2.727961273597808756e+01
+1.082812500000000000e+02 2.727961273597808756e+01
+1.110937500000000000e+02 2.727961273597808756e+01
+1.139062500000000000e+02 2.727961273597808756e+01
+1.167187500000000142e+02 2.727961273597808756e+01
+1.195312500000000000e+02 2.727961273597808756e+01
+1.223437499999999858e+02 2.727961273597808756e+01
+1.251562499999999858e+02 2.727961273597808756e+01
+1.279687499999999716e+02 2.727961273597808756e+01
+1.307812499999999716e+02 2.727961273597808756e+01
+1.335937500000000000e+02 2.727961273597808756e+01
+1.364062500000000000e+02 2.727961273597808756e+01
+1.392187500000000000e+02 2.727961273597808756e+01
+1.420312500000000000e+02 2.727961273597808756e+01
+1.448437500000000000e+02 2.727961273597808756e+01
+1.476562500000000000e+02 2.727961273597808756e+01
+1.504687500000000000e+02 2.727961273597808756e+01
+1.532812499999999716e+02 2.727961273597808756e+01
+1.560937499999999716e+02 2.727961273597808756e+01
+1.589062499999999716e+02 2.727961273597808756e+01
+1.617187500000000000e+02 2.727961273597808756e+01
+1.645312500000000000e+02 2.727961273597808756e+01
+1.673437500000000000e+02 2.727961273597808756e+01
+1.701562500000000000e+02 2.727961273597808756e+01
+1.729687500000000000e+02 2.727961273597808756e+01
+1.757812500000000000e+02 2.727961273597808756e+01
+1.785937499999999716e+02 2.727961273597808756e+01
+1.814062500000000000e+02 2.727961273597808756e+01
+1.842187499999999716e+02 2.727961273597808756e+01
+1.870312499999999716e+02 2.727961273597808756e+01
+1.898437499999999716e+02 2.727961273597808756e+01
+1.926562500000000000e+02 2.727961273597808756e+01
+1.954687500000000000e+02 2.727961273597808756e+01
+1.982812500000000000e+02 2.727961273597808756e+01
+2.010937500000000000e+02 2.727961273597808756e+01
+2.039062500000000000e+02 2.727961273597808756e+01
+2.067187500000000000e+02 2.727961273597808756e+01
+2.095312499999999716e+02 2.727961273597808756e+01
+2.123437500000000000e+02 2.727961273597808756e+01
+2.151562499999999716e+02 2.727961273597808756e+01
+2.179687499999999716e+02 2.727961273597808756e+01
+2.207812499999999716e+02 2.727961273597808756e+01
+2.235937500000000000e+02 2.727961273597808756e+01
+2.264062500000000000e+02 2.727961273597808756e+01
+2.292187499999999716e+02 2.727961273597808756e+01
+2.320312499999999716e+02 2.727961273597808756e+01
+2.348437499999999716e+02 2.727961273597808756e+01
+2.376562500000000000e+02 2.727961273597808756e+01
+8.437499999999998579e+01 2.863098983692435695e+01
+8.718749999999998579e+01 2.863098983692435695e+01
+9.000000000000000000e+01 2.863098983692435695e+01
+9.281250000000000000e+01 2.863098983692435695e+01
+9.562500000000000000e+01 2.863098983692435695e+01
+9.843750000000000000e+01 2.863098983692435695e+01
+1.012499999999999858e+02 2.863098983692435695e+01
+1.040625000000000000e+02 2.863098983692435695e+01
+1.068750000000000000e+02 2.863098983692435695e+01
+1.096875000000000000e+02 2.863098983692435695e+01
+1.124999999999999858e+02 2.863098983692435695e+01
+1.153124999999999716e+02 2.863098983692435695e+01
+1.181250000000000000e+02 2.863098983692435695e+01
+1.209375000000000000e+02 2.863098983692435695e+01
+1.237499999999999858e+02 2.863098983692435695e+01
+1.265625000000000000e+02 2.863098983692435695e+01
+1.293750000000000000e+02 2.863098983692435695e+01
+1.321875000000000000e+02 2.863098983692435695e+01
+1.350000000000000000e+02 2.863098983692435695e+01
+1.378125000000000000e+02 2.863098983692435695e+01
+1.406249999999999716e+02 2.863098983692435695e+01
+1.434374999999999716e+02 2.863098983692435695e+01
+1.462500000000000000e+02 2.863098983692435695e+01
+1.490625000000000000e+02 2.863098983692435695e+01
+1.518750000000000000e+02 2.863098983692435695e+01
+1.546875000000000000e+02 2.863098983692435695e+01
+1.575000000000000000e+02 2.863098983692435695e+01
+1.603125000000000000e+02 2.863098983692435695e+01
+1.631249999999999716e+02 2.863098983692435695e+01
+1.659375000000000000e+02 2.863098983692435695e+01
+1.687499999999999716e+02 2.863098983692435695e+01
+1.715624999999999716e+02 2.863098983692435695e+01
+1.743749999999999716e+02 2.863098983692435695e+01
+1.771875000000000000e+02 2.863098983692435695e+01
+1.800000000000000000e+02 2.863098983692435695e+01
+1.828125000000000000e+02 2.863098983692435695e+01
+1.856250000000000000e+02 2.863098983692435695e+01
+1.884375000000000000e+02 2.863098983692435695e+01
+1.912500000000000000e+02 2.863098983692435695e+01
+1.940624999999999716e+02 2.863098983692435695e+01
+1.968750000000000000e+02 2.863098983692435695e+01
+1.996874999999999716e+02 2.863098983692435695e+01
+2.024999999999999716e+02 2.863098983692435695e+01
+2.053124999999999716e+02 2.863098983692435695e+01
+2.081250000000000000e+02 2.863098983692435695e+01
+2.109375000000000000e+02 2.863098983692435695e+01
+2.137500000000000000e+02 2.863098983692435695e+01
+2.165625000000000000e+02 2.863098983692435695e+01
+2.193750000000000000e+02 2.863098983692435695e+01
+2.221875000000000000e+02 2.863098983692435695e+01
+2.249999999999999716e+02 2.863098983692435695e+01
+2.278125000000000000e+02 2.863098983692435695e+01
+2.306249999999999432e+02 2.863098983692435695e+01
+2.334375000000000284e+02 2.863098983692435695e+01
+2.362500000000000000e+02 2.863098983692435695e+01
+2.390625000000000000e+02 2.863098983692435695e+01
diff --git a/imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat b/imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat
new file mode 100644
index 0000000000..97f5f55d06
--- /dev/null
+++ b/imap_processing/glows/ancillary/imap_glows_map-of-uv-sources_20250923_v002.dat
@@ -0,0 +1,593 @@
+# Description: map of bright UV point sources provided by IMAP/GLOWS Instrument Team for ground-processing pipeline at IMAP SDC
+# version: 0.2
+# star_background_max: 2 cts/s, min_masking_angle: 0.5 deg
+# columns: object_name, ecliptic_longitude_deg, ecliptic_latitude_deg, angular_radius_for_masking
+**HDO221A 220.5517651786544 -45.67397641472249 1.6606970217308294
+HD100600 167.4557237863621 12.89523400723998 1.6077588256414592
+HD10144 345.2999797928628 -59.3822555493876 3.949782859665976
+HD10205 38.90283578666903 27.9330576386139 0.5
+HD102232 199.3413613528867 -42.35752333400007 0.5
+HD102776 217.498558640892 -56.20069044699572 3.032093346056038
+HD104337 188.2763244851311 -17.89257450772565 2.9638640821095543
+HD10516 44.59456329544094 36.85259943774157 3.4297009244038352
+HD105382 207.3797401956445 -44.4782378863903 2.9227212275468197
+HD105435 207.477505339394 -44.50507710582892 3.852636360107539
+HD105937 209.3870067173558 -45.57790496505746 3.2961323883452005
+HD106231 200.5833966875339 -33.94167851183284 0.818924317200592
+HD106490 215.6586182215707 -50.41452901356508 3.907973679548264
+HD106625 190.722136250278 -14.49915193529574 3.014973427616713
+HD106911 245.4247854438017 -63.58976637218623 2.516767482400831
+HD106983 221.7348843535212 -54.15321656928523 3.3940976950210855
+HD108248 221.8626079613174 -52.87385663223048 3.990600830858562
+HD108249 221.8643639991372 -52.87350828130606 3.9398759235414444
+HD108257 211.3458131840646 -43.53900234895308 2.723204242110102
+HD108483 210.7202100938312 -42.38338459353368 3.583951860334169
+HD109026 234.0082587704581 -58.86572327948969 3.10372844713152
+HD109387 136.2603898113016 61.75812884030718 2.644857471325639
+HD109668 230.3650752069482 -56.55203364049976 3.8959679765790307
+HD110879 230.1448857054407 -55.23788595012779 3.783782296226058
+HD110956 218.7048408105693 -46.11897626062035 2.6712528101229944
+HD111123 221.6389811067896 -48.6339997810936 3.9824845661147115
+HD112078 222.2416127231712 -47.68036988681067 2.803997614480977
+HD112091 220.5993257209313 -46.05192395165339 1.3739851809135946
+HD112092 220.6033525988453 -46.06119570760511 3.4769470557966193
+HD11241 48.61204112052373 40.25742617866466 2.730894315538438
+HD113120 236.1715434027645 -56.67321504030481 1.457244906481816
+HD113791 217.5575621422381 -38.90810301164772 3.438437005032535
+HD113904 229.849278254858 -51.7077423122129 1.9640464004235494
+HD11415 54.7667983239087 47.54996902321451 3.309074398300144
+HD115823 221.7895262615498 -40.3356831437719 0.7024534820865025
+HD116087 228.0397878713512 -47.24343447914939 2.9172857508198966
+HD116658 203.8361967375125 -2.053637856126439 3.985319656741486
+HD118716 225.5475309731738 -39.58183441315738 3.9481212533887367
+HD119159 228.135009270748 -42.27805217947525 1.3553845148126018
+HD120307 221.1476582320562 -28.26458606042002 3.8081790318770716
+HD120315 176.9293997037208 54.38332565228174 3.8624113169136405
+HD120324 221.5295662675227 -28.97576851336546 3.731612479689779
+HD120640 224.058717794563 -32.85150157807229 2.311063396077932
+HD120709 217.9239411125802 -20.06993178924361 2.7709852540298314
+HD120955 217.7899194016693 -18.97165934073297 2.111459438632786
+HD120991 224.572436287607 -32.90587852078553 1.5491778430626542
+HD121263 224.9435598119471 -32.93963128741022 3.926481390462596
+HD121743 223.0314835451847 -27.99696741331314 3.665605573602182
+HD121790 224.3368096175587 -30.44897459834967 3.6142417931377806
+HD122451 233.7837493902261 -44.13344067688722 3.989749682182295
+HD122980 224.1400171590028 -26.58717207762544 3.3570816508770656
+HD124367 233.4987487662803 -40.55039629572567 1.8653973894348073
+HD125238 228.7812051063511 -30.18806017895736 3.5287543528436025
+HD125823 226.7949295734094 -23.85047659365588 3.2668199430662637
+HD126341 229.6802183487772 -28.9741635493817 3.3076702924467467
+HD127381 233.1260222416927 -33.4363929417204 3.429785108985421
+HD127972 230.2413817475586 -25.50984187429617 3.8922631593801693
+HD128345 233.6110786630236 -32.16521866191106 3.077693342561764
+HD129056 233.4958841149739 -30.02246251354698 3.928812387876518
+HD129116 229.9258046749871 -20.98366260832786 3.3795537523308163
+HD129557 237.6478379361048 -37.49455708602182 1.5291747559288176
+HD130807 233.8574528241256 -25.86010437509977 2.8070361886659496
+HD131120 232.1097940606775 -20.31169416071087 2.5762386160811004
+HD132058 235.0176020425583 -25.04308020608494 3.881770068937574
+HD132200 234.7868202155679 -24.02838367622277 3.7850431107120155
+HD133242 237.6238424976819 -28.40104475761623 3.167450201022979
+HD133518 239.794196904418 -33.02614916128913 0.7868205200940329
+HD1337 29.74563216962104 44.28652592817018 1.264200337900796
+HD133955 237.7022785145865 -26.51729608701172 3.3691199986173115
+HD134687 238.1932933982993 -25.56315768738658 2.9919643900896538
+HD135160 245.087398144859 -40.94488532676156 2.5581867886310876
+HD135240 245.1625268290208 -40.98080681653997 2.9109240705579325
+HD135348 238.5040540363126 -24.41681697575999 0.7260732925685239
+HD135591 245.2387607882119 -40.46955324009502 2.675107012576731
+HD135734 240.3650852458649 -28.49945205331298 1.3920663215729117
+HD135742 229.363981547336 8.496488066441744 2.527676796833355
+HD135876 238.2137298496107 -21.68497677077901 0.5
+HD136298 238.6486519324457 -21.42308668653292 3.842007010218848
+HD136415 245.4340659727026 -39.17116040013449 1.9360489882939171
+HD136504 240.1139074219356 -25.24216372075354 3.6797232731329452
+HD136664 237.9255648543264 -17.67988472996759 2.9616623257305963
+HD137387 253.6969234939286 -52.04468262631801 2.5739000979360465
+HD137432 238.7408239602275 -17.37571608073401 1.8569484531274432
+HD138485 235.0092679762813 2.234043786490918 2.479363930070505
+HD138690 241.4895512161424 -21.24126859629524 3.818862428750428
+HD138749 219.4408418686138 48.54936455600912 2.5971531563681474
+HD138769 242.6834453404838 -24.87269660098251 3.086674562281213
+HD139365 239.3428147511154 -10.01878148814506 3.5039584886894897
+HD140008 241.3651219050368 -14.61780368452253 2.438921557039112
+HD141318 248.3722586744198 -34.00534768957143 0.5058614906076241
+HD141637 241.1165221245912 -5.485843685329233 2.809203226050414
+HD142096 240.467676717571 0.08671310210629236 2.1268177806092132
+HD142114 241.6094428826658 -4.945841517591909 2.8527999172781318
+HD142184 241.3981235849363 -3.611473542622911 1.2404232036436276
+HD14228 0.9915356997786365 -58.99053524621088 2.433357564188525
+HD142669 243.1379275505345 -8.59711747470106 3.5629708954677586
+HD142983 240.3910011624127 6.08648192584367 1.3657474487686347
+HD142990 242.6119634332167 -4.229709055160963 1.417550341316766
+HD143018 242.9314618934856 -5.473614122661374 3.872466220476765
+HD143118 245.7628010097515 -17.44222506434041 3.7730136513582915
+HD143275 242.5628113033524 -1.984511073574772 3.880569946776771
+HD143699 246.4657685845784 -17.51159337756686 2.0240398481669546
+HD144217 243.1815297306112 1.009130292946089 3.8073785672272367
+HD144294 246.7356998822269 -15.62174224004856 3.3582139952636503
+HD144470 243.6608357739194 0.2220519488733443 3.3461805074386954
+HD145482 246.2370653168167 -6.678493470103522 3.2205323653687996
+HD145502 244.635224445188 1.634618185961501 3.139547736511682
+HD14633 47.54758981897872 25.70275369040248 0.6277527138288959
+HD147165 247.7908810957959 -4.035667088577588 3.545069750664864
+HD147394 224.3701480607625 65.82662974963124 2.9357867890322464
+HD147933 248.4286115327472 -1.755893417437619 1.8445907291821886
+HD147971 252.8586602542358 -25.48348940261253 2.437962656359332
+HD148184 247.9704219422019 3.225029350258386 1.8605584068273209
+HD148478 249.7534751557471 -4.568213009403136 1.8488494948912622
+HD148605 249.7301293581026 -3.239439740014505 2.966216491054584
+HD148703 251.4631244749457 -12.67704123289122 3.434009859474025
+HD149038 253.5204944347543 -21.82396582799501 1.9076541330671892
+HD149438 251.4479965442499 -6.118594826186319 3.931132196995904
+HD149757 249.2201574348453 11.39222943974934 3.4418655019351836
+HD149881 244.8504036839993 36.11993068912476 0.5
+HD150136 255.6648608130951 -26.29438614411605 0.5
+HD150168 255.8733320515258 -27.1648704715698 1.1616816489580428
+HD150745 258.2492338225235 -35.80955629638579 1.445331536094747
+HD150898 258.3736961701731 -35.62974109483002 1.9445245218298086
+HD151804 256.4912502144165 -18.58741265508414 1.1866918406490266
+HD151890 256.1463234432671 -15.42097660211652 3.845938309689643
+HD151985 256.2369742478399 -15.38029220799489 3.728633034346993
+HD153261 260.7755246154904 -35.98083889747451 1.8835010884723433
+HD15371 7.928766346788021 -57.01775068409475 2.1275872103657587
+HD154445 255.2993345905223 21.85615245893293 0.5
+HD155763 183.366801474668 84.75592607823198 2.7381322561541666
+HD155806 260.5408161910066 -10.47288816449534 2.1352838190510326
+HD156633 253.908369046824 55.94488841939285 3.1409360891657756
+HD156838 264.6791349978345 -39.58798899800786 2.1216252794231347
+HD157042 263.1951110135275 -24.24300047485345 2.551708210860597
+HD157056 261.3855051917688 -1.84188120850219 3.8370324387419648
+HD157246 264.2828222047779 -33.10723158615035 3.620328677703313
+HD158094 265.5458622983724 -37.35346645391861 1.965747752809858
+HD158408 264.0031270475694 -14.00633213895805 3.8905404212486934
+HD158427 264.9242108675091 -26.55829515792518 3.6455494959690586
+HD158926 264.5761415923018 -13.78649538541274 3.967833383123908
+HD159176 264.595255992402 -9.258872330840019 1.3722845488194089
+HD160578 266.4597672179309 -15.64236961419499 3.9350408976826334
+HD160762 259.8692741702429 69.26517777347354 3.40097323073559
+HD161783 268.3552606919537 -30.18442959232015 1.4849909233440262
+HD162374 268.3629359176073 -11.36905751768403 0.6893024250195603
+HD162978 268.8336552913933 -1.451302668527286 0.5
+HD164284 270.0639009055378 27.8090011318239 2.9783478349252115
+HD164353 270.1695836257826 26.37188408959548 1.6063847190619478
+HD164402 270.4298577011072 0.6598525910576597 1.7694903151900514
+HD164432 270.2416362956859 29.70848227706545 0.8030158639196776
+HD164794 270.8728087724799 -0.9228017851274242 1.1942766713812158
+HD164852 270.7661667940534 44.27223252796123 1.8297946089793224
+HD165024 271.1797365409898 -26.65702720759356 3.3127786020470418
+HD165174 271.2679551070599 25.35436008926705 0.9082848860403764
+HD16582 37.56988750609379 -14.46397742733597 3.4832019493119133
+HD166182 272.8450688976941 44.23319841781023 3.2136298824914866
+HD166197 272.2969086545594 -10.38090863625922 1.8610354320006155
+HD166596 272.5960614833043 -17.92486608891642 2.052156594043077
+HD167128 272.8287429316112 -32.62425932514096 1.1787871182375882
+HD167263 273.5606966091484 3.005748861105073 1.3612676297275523
+HD167264 273.5514479881294 2.665572660944637 1.906043864199993
+HD167756 273.6381223683608 -18.90638658435738 1.5195206418120875
+HD168905 274.6521064755974 -20.76745505197985 2.632494802386186
+HD169022 275.068767039434 -11.050116896869 0.5
+HD169467 275.0633854137681 -22.64607127996284 3.4971954929418856
+HD170523 276.0282745046574 -22.4840641351812 1.7800061508727152
+HD17081 33.75381432322347 -28.25128279949267 1.863280082448374
+HD172167 285.301134338644 61.73483515807342 2.022163619658343
+HD172910 279.1979393657285 -12.55461563951692 3.0824472498506603
+HD173300 280.1716520313912 -3.952466574093894 2.340642355076453
+HD173948 277.7936322455269 -39.09980607620747 3.3431396129611564
+HD174237 298.6065370222753 75.26865959547739 1.6198430907747785
+HD174638 288.8703762528111 55.98636451700425 2.4053198527497703
+HD175191 282.3756622342877 -3.448004972777734 3.9082897091617874
+HD175362 281.5843241364336 -14.47098044714269 1.5300160942070264
+HD17543 45.13623140302347 1.13721233801385 0.5
+HD17573 48.20346742966826 10.4493310632815 2.001628700943403
+HD175876 283.6141708419307 2.331854401861034 0.6222031349681674
+HD176162 284.6810506180383 9.846326612822015 0.5
+HD177003 302.7963769805381 72.26363398449513 2.6664064912851226
+HD177756 287.3226036444804 17.56746825963542 1.3896266432090705
+HD178175 286.1006043070824 3.201010532688972 1.6428294389111417
+HD178475 296.1913188842175 58.02129368654602 0.7397500281432772
+HD180163 300.0441492275532 60.67838601302219 2.7468950359253523
+HD180554 294.6395866792925 43.21514582556603 1.5096514843899935
+HD180885 286.5514999828698 -13.11884475692466 1.516052955617253
+HD180968 295.531263808097 44.75927813887718 0.7791369649362748
+HD181454 285.7657403225892 -22.14334398274557 1.1858675920377895
+HD181869 286.625691914938 -18.37882817104005 1.406840312567618
+HD182180 288.6686913056575 -5.784790658355691 1.1257125501526917
+HD182255 298.1049943037033 47.70285031790944 1.439133215813593
+HD182568 299.6489336823554 50.9201008817684 0.8187715671552571
+HD183362 304.5662917584521 58.7827926146524 0.5
+HD184171 304.2624623850454 55.19857506642366 2.5556970296627033
+HD184606 299.8908849507141 40.79217412283626 0.5
+HD184915 294.8446301632607 14.34805209834945 2.407143744687944
+HD185507 297.7969566517208 26.47693049783005 1.4356450160190515
+HD18604 45.0925218202385 -7.787726675843721 1.1758332361817616
+HD187811 305.7808358868141 42.6635185516548 2.6170225187839278
+HD188209 320.7659918504063 65.60909926650135 1.851724498043101
+HD188439 322.0261568842 66.22175665106991 1.318172294456294
+HD188665 338.928794589094 74.16333075545398 1.8497322683612585
+HD188892 314.8607330793124 57.50398984283832 1.0790921156065816
+HD189103 294.8601946820789 -14.38461976510368 3.1335766486264687
+HD189687 315.2883291993556 55.86919765775156 2.500977466811176
+HD190993 310.9135386310082 42.65511983234813 2.75713507350323
+HD191610 318.2787744978814 54.9907617289905 2.709400915834265
+HD192685 314.2175045693601 43.98088871138737 2.9961359575191637
+HD19356 56.16856568195753 22.42874273875529 3.062467563418873
+HD19374 49.39751308285643 0.3121984827611352 1.7547077716935675
+HD193924 293.8061430214473 -36.26696584961712 3.9127133265235785
+HD194335 323.2611489751303 54.47574580062392 2.570388263658058
+HD195810 314.0522620241584 29.07585262884356 2.2911575170376235
+HD196740 320.3466491097565 40.88351710515472 1.760990930153185
+HD196867 317.3719627927612 33.02530367595787 0.5
+HD197511 341.5111178494035 64.06010804858565 2.017595675080896
+HD1976 31.37734503794811 44.21513273866593 0.64392641054671
+HD198183 329.7381671904367 51.61629977784898 2.1831474993386175
+HD199081 337.914694765267 58.06689057625683 2.2642554187440522
+HD199140 326.9611652188684 43.73057991926999 0.816602594637529
+HD199579 339.4039725408763 58.2169230517101 2.936443307639392
+HD199661 355.9423730453306 67.6146090029602 1.652039564684864
+HD200120 343.081416767838 60.08892082629556 3.2829507664353623
+HD200310 341.9707021913183 58.82434500595013 3.011411182234774
+HD202349 338.2155177428942 50.38716224756158 0.5
+HD202654 347.8845774481581 58.94013852394399 0.5
+HD202904 337.2508861495436 47.46911293563516 3.086649533947961
+HD203064 344.5052727816858 55.31869118358836 2.63457639349001
+HD203245 350.6781622884444 59.80043596946801 0.5
+HD20336 67.8876613780196 45.25691069364624 2.9703794267994303
+HD203467 18.54854664313843 69.98645218226491 0.7889596747611237
+HD20365 61.19262821378637 30.73995452713248 1.732733477764753
+HD204172 340.5746861020045 48.31378650487341 1.0624368789222078
+HD20418 61.23694189475041 30.59468971892902 1.488105455764569
+HD205021 35.55382122068505 71.15679981541103 3.838500040156783
+HD205637 320.1906099811483 -4.975320568240591 3.05140641267138
+HD206672 358.2729375723088 58.88055176790461 2.4173274025029903
+HD207330 357.1791519794247 56.94104244113259 2.8962565467576775
+HD207971 317.4099211445853 -23.05055684824143 2.483310109074095
+HD208057 341.2130885375776 36.10998904478216 2.511960642488235
+HD20809 61.66936551079105 29.55728026042822 0.9491792671048074
+HD208682 24.57645557990949 66.86052827391102 1.2884313932184401
+HD209409 332.1000258384177 9.164455543871348 0.5
+HD209481 12.00106212637222 61.86597578240075 0.5
+HD209522 323.6761069027592 -14.04742409996034 1.5724661509700808
+HD209952 315.8967554603643 -32.91397030252615 3.6407070160948813
+HD209975 19.82857694848091 64.30432805558738 0.8420141846487355
+HD210191 327.6432949824037 -6.647952307023034 1.4972572170427112
+HD210424 330.4793330949786 -0.2819464446874886 0.5
+HD212076 341.9476794417931 20.85328110342268 2.7853095045081564
+HD212120 2.24704758851184 51.306178866413 1.9575663880241927
+HD212571 338.5913630617895 10.47441976535403 3.2383290605090025
+HD21278 62.48948006271451 29.18806648760998 1.8912003975029348
+HD212978 358.1888998900686 45.03507636005848 1.6412739656540565
+HD213420 1.436047169368364 47.53990610936478 2.6419839189028727
+HD21364 51.91181032098904 -8.800491453182168 2.2659105454765633
+HD214168 0.003022871071769546 44.04145674290447 2.6253870874663447
+HD21428 62.86926988644709 29.55623201970648 2.397771914148775
+HD214680 0.3696678666945258 43.20839215173743 3.334843191094381
+HD214748 331.3205663014655 -17.27392356634206 0.98689987263317
+HD214923 346.1457434967027 17.68144516025289 0.9275881607224499
+HD214993 1.712475988222833 43.99439958248446 2.7320169373700502
+HD215573 290.4311040806576 -62.06415601169032 1.064966430865893
+HD216916 6.041366382208924 43.68782846463914 2.5859638084054524
+HD21699 62.90462627734828 28.00217025363703 0.5
+HD217050 11.95140920314773 49.49515607513559 1.7248827935978956
+HD217101 4.700310750760201 41.60088199792271 1.9549587113489217
+HD217675 7.776721935592812 43.75401820497326 2.5840660205656016
+HD217891 348.5795978811377 9.05423771887832 2.139719969340857
+HD218376 25.3689121727993 56.7858589572722 2.5418171773622196
+HD21856 59.49940126819101 15.84065280030461 1.8208899806258776
+HD219688 346.7232018257094 -4.283397107439385 2.156235403427308
+HD221253 28.1612889659257 54.07546528335547 2.4331331152733675
+HD22192 63.74756559611011 27.97108983612361 2.2297584600393554
+HD22203 44.20434374328553 -39.44399678572422 1.4671252326565545
+HD222173 16.08297550299402 41.03249075264046 0.5
+HD224572 30.12990706811282 49.41410313578308 2.596260779907081
+HD22928 64.80384669574742 27.30183995913278 3.152531992198737
+HD22951 61.13272299663606 13.90915670564499 2.655794255732703
+HD23180 61.14409536805194 12.18375191480918 2.655945217080091
+HD23227 41.97309715713912 -49.80108473986667 2.134849855737973
+HD23302 59.41248204149063 4.188742983375155 2.174061545971467
+HD23338 59.56527952382052 4.517112699210209 1.8439647912178665
+HD23408 59.68096472936413 4.388922858369018 1.6682410394571485
+HD23466 55.55705483175537 -13.46679135673735 1.8096979911280675
+HD23480 59.69986905249151 3.95471427251631 1.2964662108343066
+HD23630 59.99299904781045 4.049831697085026 2.430213929167834
+HD23793 57.34918482644228 -8.643346923981941 2.3011953747560474
+HD23850 60.35653424830873 3.916343548930738 1.118205132221874
+HD24131 63.20028661063159 13.85121898173112 2.076354496370479
+HD24398 63.12482313984223 11.33276610747693 3.0168197009971554
+HD24504 67.21293173121735 26.85565173928638 0.5
+HD24626 43.99714708101814 -53.24955340047858 1.6206071647377192
+HD24640 64.30811486208921 14.35473201132976 2.2405411520460627
+HD24760 65.67918832081493 19.11418642606991 3.871568122519173
+HD24912 64.97364414876866 14.94325854585973 3.1283043328845785
+HD25204 60.63502068280096 -7.961714624650352 3.4252845357167963
+HD25340 57.86910299805602 -21.74889365225252 1.5786181073263634
+HD25558 59.95291751637387 -15.02576278777962 1.539647621933297
+HD25940 69.49945314126995 26.23489840185148 2.5157418429630756
+HD26326 56.26684267129101 -36.64378262607664 1.7092848761029475
+HD26356 85.06868828921473 60.76404339776268 1.1426351337701808
+HD26670 74.5174960732736 39.78949468757975 0.5
+HD26912 63.58202144418815 -12.18597150163279 2.0098456100352093
+HD27192 72.29991931369298 29.00373581065915 1.4372244141395345
+HD27376 52.50419025283911 -53.96956190676705 1.9996198786325867
+HD27396 71.62019159770662 24.61752401047836 1.4990516272192065
+HD28497 62.8796913351628 -34.37636584205064 2.8982016332740526
+HD28873 49.98595581177828 -65.3308738981256 3.1151721881652676
+HD2905 42.60297296678146 52.28304069203725 1.1060641118146974
+HD29248 66.816018198754 -25.1263885314799 3.584837547551422
+HD29305 37.8310614786008 -74.58768290282188 0.6758975064288111
+HD29335 67.78582096707645 -20.8618473982947 1.0533847057964196
+HD29589 70.17928448072541 -9.878999511413962 0.5
+HD29763 72.15491135127512 0.7124089577671937 2.95907101349558
+HD30076 68.08115449641497 -30.51310663264505 1.2907077165553562
+HD30211 69.33822867450671 -25.3705945143857 2.890975589033715
+HD30614 80.9834696340941 43.4186535069068 2.34974320604012
+HD30836 72.10212808024694 -16.77421189144184 3.4563454132117513
+HD31237 72.4922073167929 -20.00752911527131 3.477824862215742
+HD31512 72.06659502307774 -27.62890816971096 1.3492281636129564
+HD31726 71.08583804528675 -36.65792462475397 2.530631438614215
+HD32249 73.2109222795402 -29.76670480306573 3.050058551486632
+HD32343 81.47898041573066 35.93039472601452 1.9986003458226866
+HD32612 72.90230167778847 -36.98332559322031 1.8304538695720918
+HD32630 79.44810778678874 18.28289949963841 3.5520810815737542
+HD33328 75.21539291126399 -31.54592541088518 3.446931060848576
+HD3360 35.0660433752386 44.72256414158453 3.627633275581227
+HD3369 22.67758908964007 27.15085275240332 2.595162340236905
+HD3379 14.4783270868555 10.35291741797487 1.90677945243172
+HD33802 75.75964169758501 -34.72367811046866 0.9933246815112681
+HD33904 75.39690258454205 -39.05308741727819 1.9838237916885524
+HD33949 75.9064117400066 -35.81314949628246 0.6897468555182963
+HD34085 76.83170013230679 -31.12551688547017 3.5968863340907413
+HD34503 77.8492979454897 -29.84033963313137 2.7748293374504174
+HD34748 78.89390986889819 -24.46491534365881 1.1318523133528209
+HD34759 82.50501955973883 18.61244241559209 2.038331933657641
+HD34816 77.78099112394862 -36.19117456608251 3.6761339441070637
+HD34989 80.2147434710535 -14.68831332268659 2.4848601014476137
+HD35007 79.50514046352971 -23.50841408330923 1.9855164392269198
+HD35039 79.5708285479085 -23.4786726221748 3.264504556377801
+HD35149 80.15354831214538 -19.58000632399114 2.87333152755907
+HD35299 80.11567697606183 -23.29061321487118 2.9477134631354507
+HD35337 78.88862284973004 -37.01811716504589 3.1190573197855924
+HD35407 80.53813786411284 -20.7981430318301 0.5
+HD35411 80.15962599421644 -25.53595733044366 3.7941331539006997
+HD35439 80.54146812660264 -21.30616978032727 3.26933514286857
+HD35468 80.9482230086287 -16.81817479038772 3.9542118398795987
+HD35497 82.57662144865361 5.383693460372124 3.5305021769907814
+HD35588 80.72769813664256 -22.64640204745584 1.9810006053435092
+HD35671 82.16316528727226 -5.255769596267188 1.2947432108303787
+HD35708 82.4977547375792 -1.293427325152861 3.0720049391621127
+HD35715 81.18283426405512 -20.09239807143259 3.469718686649373
+HD358 14.30578248276592 25.68254564780333 3.15388966669137
+HD36166 81.92137734335981 -21.44154369207044 2.821185725042048
+HD36267 82.39128092463666 -17.30051397196065 2.848409168034912
+HD36285 81.4491218408955 -30.6567892347092 0.9197507675699592
+HD36351 82.36319504395576 -19.95891577123335 2.8404923557202455
+HD36430 81.78580044496124 -29.94609483839902 1.8112839634047142
+HD36486 82.36417067897969 -23.5553230579875 3.9430146774325676
+HD36512 81.91394346656857 -30.54652509200857 3.623654541263965
+HD36576 83.70662152051852 -4.756277507427733 0.7767825943431105
+HD36591 82.47662108673335 -24.85526083052818 3.2103847178953098
+HD36653 83.602122731704 -8.990748516339902 1.91270940847541
+HD36695 82.73045894821489 -24.43074873163469 3.0284365984067927
+HD36779 82.88523718046497 -24.31727673791441 2.037871591958087
+HD36819 84.3983763456826 0.7180229796854748 1.7731926315230133
+HD36822 83.6078635341577 -13.81208806046832 3.3975182349607618
+HD36824 83.40209536741747 -17.63584759099028 0.5
+HD36827 82.83498541621893 -26.16327571427758 0.6587114123221456
+HD36861 83.70862601606872 -13.37142823602589 3.71397322372972
+HD36959 82.87579623220512 -29.2966147163635 3.010581493006157
+HD36960 82.88415371199089 -29.2897260554957 3.515059976935772
+HD37017 83.0585180440714 -27.78752371466826 1.185909713654162
+HD37018 83.045807148902 -28.13157186254682 3.4507340772792787
+HD37020 82.98092269384723 -28.67841725619552 1.5203181848395897
+HD37022 82.98380669165456 -28.68090926665507 3.0352515428802596
+HD37023 82.98765219584627 -28.67932711161706 2.151919995857059
+HD37041 83.01275472128171 -28.70855894490743 3.0829926399816885
+HD37042 83.02923457488465 -28.71008840546001 2.118141802800813
+HD37043 82.99988003274319 -29.20244917508623 3.918839470689083
+HD37055 83.19058932928571 -26.55035134021889 0.5768853599167914
+HD37128 83.46578226433977 -24.50866742444512 3.9446704122668486
+HD37202 84.78633848315525 -2.197270524652341 3.7169190605527764
+HD37209 83.32227796842537 -29.37087810078352 3.0018196981154484
+HD37232 84.21999900312336 -14.37568353539611 2.3593198782559415
+HD37303 83.57416155861819 -29.25440532582486 2.824955354975846
+HD37356 83.75361185839651 -28.1358720104134 1.163976241640286
+HD37397 84.02043531734455 -24.49778435913703 0.5
+HD37438 85.4412722358242 2.536444025208726 2.2818475986840214
+HD37468 84.09803602991394 -25.9328310795069 3.7693738401468555
+HD37479 84.10956269323141 -25.92775876055498 1.4441210457879958
+HD37481 83.87822503037192 -29.90216242298187 2.863046079824707
+HD37490 84.5046802023943 -19.22069028165048 2.74757398844151
+HD37711 85.487214445997 -6.833659625676039 2.715332929040847
+HD37742 84.68354919798827 -25.29535316586324 3.9562905951679235
+HD37744 84.60916403909707 -26.17615794457546 2.4584201004171193
+HD37756 84.7402320359027 -24.48288707223807 3.2160680968734674
+HD37776 84.75097846150894 -24.86189778181858 0.5
+HD37795 82.1752340933897 -57.37828638786981 3.18192447840132
+HD38666 84.75403879186746 -55.6848068626518 3.448661099523398
+HD38771 86.40139886423032 -33.07299387554057 3.9111849122696656
+HD3901 33.47772152311376 41.44851950490064 2.2074913157030718
+HD39291 87.50766117877576 -30.94085803962857 2.942052673958476
+HD39698 88.80989393941599 -3.686110642828733 2.0403798366956347
+HD39764 87.36364104900424 -57.22755313940836 2.2713601234699103
+HD39777 88.4782557287212 -27.49897716971671 1.8814202590294304
+HD40111 89.55052724360148 2.513860324263009 2.633749499044839
+HD40494 89.03884892150616 -58.7230726453023 2.9856933796337346
+HD40967 90.5487769257452 -34.03850021406884 2.8330822690106348
+HD41040 90.81708768863956 -3.747937033128643 0.5
+HD41335 91.21585662249615 -30.1458521197777 2.550732749943607
+HD4142 32.13797103436885 38.97474448492478 0.9764782920550592
+HD41534 91.63141993614343 -55.60792446968871 2.4796725241968147
+HD41692 91.87279596659076 -27.62432966511573 0.8149488976402923
+HD41753 91.85350424900292 -8.660372652878904 3.274774891698815
+HD4180 32.4645307512472 39.31376089842917 1.720170540152528
+HD42545 92.92038314742298 -7.28004602062208 2.325792217456195
+HD42560 92.93329182938139 -9.201868479523599 3.0437102405757614
+HD42690 93.40410643589831 -29.9565084736228 3.001474060157117
+HD42933 97.35731816665024 -78.34427910345244 3.5123430003911533
+HD43112 93.72865955111094 -9.540934681112919 3.2024952797940256
+HD43317 94.1667088379599 -19.10042415193886 1.0352174140037997
+HD43544 95.04877400336598 -39.98864604879205 2.1461401097105477
+HD43955 95.89510519593142 -43.315014903289 2.4794356044868504
+HD44112 95.71129880973734 -31.16641963106051 2.7629022621905612
+HD44402 97.38369328698123 -53.37450571690296 3.7382808890034633
+HD44458 96.41200008904474 -35.09533525325748 1.2864257202130633
+HD44506 97.94358068253061 -57.4433993434594 2.599584659774422
+HD44700 96.17380795958177 -19.55177906344965 0.5175065010774833
+HD44701 96.43165886592706 -26.58965216311441 0.5
+HD44743 97.19194425625267 -41.25550984679086 3.9595727573337696
+HD45542 96.80436507933469 -3.057940261309825 2.3657962643320714
+HD45546 97.89813349692497 -28.01176959074315 2.9688842125191504
+HD45725 98.28863434221861 -30.26705302308791 3.11129673816863
+HD45726 98.29041523094952 -30.26830617890667 3.354835090821121
+HD45813 100.5875045143453 -55.76253724487968 2.895326186627154
+HD45995 97.81235998079717 -11.97859736425997 1.4465836956411755
+HD46328 100.6610588417655 -46.56509101488241 3.652988880236158
+HD46487 99.23929379782545 -24.39186943109071 2.005375006523605
+HD4727 29.14853957963244 32.56432662065107 2.4132564514246133
+HD47670 107.1593025467824 -66.07508718069836 2.1584352019196396
+HD47839 100.3683132262582 -13.17721930654107 3.543141897015903
+HD47887 100.4465878132523 -13.60257232864399 1.545417754958629
+HD48879 96.76941943429158 44.43024433886698 2.406862357455736
+HD48915 104.0856185890856 -39.60655633399273 3.018916781410106
+HD48917 106.280314178988 -53.88452179415313 2.6600741771519973
+HD48977 101.8820596903383 -14.3751116283304 2.1429481271300035
+HD49567 103.2340012220926 -21.87706127842667 0.557968687399681
+HD49662 105.04543631783 -37.94826768961872 1.3409308589188684
+HD49798 112.2638424904283 -66.82978542898833 0.9452619690747565
+HD50013 108.5731161743192 -55.14836836545499 3.723752538959549
+HD50707 107.2465431454904 -42.86659838023175 3.3782623025947704
+HD50896 108.1434489298285 -46.51872189752057 2.1642614058474132
+HD51283 108.4617973491627 -45.49213994206035 2.291086297787117
+HD51309 107.5263921982975 -39.6447244345301 1.8846967955661753
+HD52089 110.768839814486 -51.36088888778117 3.955969381362092
+HD52918 107.6200407571484 -26.72289688514268 3.1884053782645765
+HD53138 111.007732904551 -46.13108522473701 3.101258185416491
+HD53244 109.6116741004595 -37.99473826668986 1.8525326062010241
+HD5394 43.93343537225485 48.81741927606038 3.9182482053290104
+HD53974 109.741471972914 -33.59907204951485 0.5986066011711411
+HD53975 109.9012836276324 -34.69119005141449 1.5193332234067674
+HD54031 113.8096502148319 -52.74032733226732 0.5
+HD54309 112.4247730242699 -45.97820199391469 2.2575134302599364
+HD54669 112.9434986602268 -46.12288027275219 1.5397896594661107
+HD54893 118.4364687017776 -61.40684099273654 2.8782942085622767
+HD55857 115.4073863502163 -49.18593389206194 2.909354951128899
+HD55879 111.8310544292873 -32.35639191435826 2.5409103855215136
+HD56014 115.3310233668461 -48.1730675999512 3.3170236040330856
+HD56139 115.6362189000713 -48.56159271432409 3.2534610573259264
+HD57060 116.2655727814582 -46.22124188076423 3.1652804899581435
+HD57061 116.3884528432375 -46.6078156300791 3.3897211171897856
+HD57150 120.5627115752057 -58.11419077784162 2.9321819983343387
+HD57193 116.7127478962068 -47.18705628376782 0.5458550014781027
+HD5737 0.4866526128962675 -32.5162965387704 2.0057556154233334
+HD57682 113.746383758602 -30.74454678100015 2.205293257911814
+HD58050 110.4473521486515 -6.437323827143812 1.9333291124698269
+HD58343 116.0144460548409 -37.74918631681582 1.3494438987177826
+HD58350 119.5421943025794 -50.60867315343125 3.115262256223205
+HD58715 112.1938120090132 -13.48841662443511 2.350985991430475
+HD58978 118.4972006891425 -44.3977376642469 2.8364244847395685
+HD59635 125.6266108606187 -59.5265098380572 1.883274615917561
+HD60606 125.9570392913353 -56.88529476141778 1.9890280866175716
+HD60848 113.2432554607658 -4.59930177104787 1.5637527923538292
+HD60855 118.9704315301989 -35.54847587071666 1.2453351573262015
+HD61556 123.4629361898253 -47.41361552729239 2.816836488301117
+HD61831 129.0629323396222 -58.42182103270561 2.8722742879574894
+HD62226 129.8430320361386 -58.5209753401079 1.6154140989822539
+HD62747 124.5126615443759 -45.0307679400573 2.7233952991960697
+HD63425 133.9754015338794 -60.91756428105259 1.623864177912398
+HD63462 126.06871019213 -46.05022009046807 3.4441622514046752
+HD63465 131.9889568488376 -58.09898083706428 2.275492117836028
+HD63578 138.6837421752017 -65.56539175579529 3.210467983368398
+HD63922 139.0752546952996 -65.22520900895461 3.553231874333241
+HD64503 134.0295721318126 -58.07400219840361 3.249201353243965
+HD64740 144.2942011143201 -67.7925927595709 3.494095183198588
+HD64760 142.4969856158885 -66.45312748687087 3.4375804361648052
+HD64802 132.6846774744697 -55.165438117992 2.594695431574018
+HD65575 150.7401565077767 -70.32320733630574 3.4851964693881303
+HD65818 145.7121594764425 -67.05193991630078 3.467124080971908
+HD65904 141.443919382198 -63.43626958036204 1.2038689879594962
+HD66194 170.3442405328395 -75.80796960587426 1.760556459093595
+HD66591 180.7251938432828 -77.10035785337425 2.775592570792785
+HD66665 122.0361046525736 -13.85196168938906 0.9989896161846997
+HD66811 138.5575164176921 -58.34575626845221 3.9641992013521103
+HD67536 178.9278952266409 -76.32065854960973 1.087749586326161
+HD67621 147.7613367358769 -65.70406732560848 2.1003619590515443
+HD67797 129.9611013520567 -38.31542131669725 2.7708656366371898
+HD67880 129.0937741394104 -35.39892403870009 2.3421317291865273
+HD6811 36.42196222460615 36.37173022835822 1.4118390167498402
+HD68217 144.0365818471556 -61.62088195534698 2.7911288035971293
+HD68243 147.3526956644006 -64.4724451525996 3.649026796110927
+HD68273 147.3577008056741 -64.46120824598222 3.9707497488568397
+HD68520 204.1641015197276 -77.77383828097521 2.0188091306450535
+HD6882 342.3683348922673 -55.1354349442767 2.416532312401919
+HD68980 139.0009934997156 -53.80842950631056 3.217739637336902
+HD69081 139.4220593489969 -54.16453917177678 3.0314726547825046
+HD69082 139.4359749191566 -54.18119863178379 1.6137975641924647
+HD69404 148.2014799940385 -63.27318729804026 1.7697870093612647
+HD70309 151.5762646845919 -64.38310297610515 1.19364727073398
+HD70556 141.8589529767858 -53.74667246251474 3.0418604795367883
+HD70930 153.0528962165233 -64.32859219508772 3.277274474470606
+HD71129 173.1361455717689 -72.6748099604712 3.2606802398020185
+HD71459 147.5667043449988 -58.52467478931171 2.193091447467914
+HD72014 148.8943452506877 -58.65696331782161 2.180837366841515
+HD72067 150.4330791114062 -60.02104329176674 2.2313761810260693
+HD72127 151.0905670811174 -60.4853864614585 2.998374115518499
+HD72232 152.8566535142759 -61.84909803577724 0.9364231063932318
+HD72555 154.4648982054754 -62.45600835266078 0.8628303183371409
+HD74195 164.7398971658832 -66.27199946056113 3.4058701051151945
+HD74196 164.8876714112637 -66.34422977968545 0.5
+HD74234 158.4382263389604 -62.44173567779077 1.1837618646798338
+HD74273 159.350931283072 -63.00042035616205 2.8295916214209496
+HD74280 132.3054878306154 -14.25121718010685 3.2683613783088106
+HD74375 178.3291749012886 -71.03580403464662 3.1044302207363734
+HD74455 158.6991513965356 -62.20884661334935 3.0354402564777923
+HD74531 158.8685370774266 -62.23365434097715 0.7790357785164079
+HD74560 165.6561445436649 -66.21487646197434 2.660181632348276
+HD74575 146.5042297183924 -48.92062878569545 3.677296837854992
+HD74753 161.2652779252857 -63.49480756459297 3.2698507032341406
+HD75311 173.3056983260745 -68.47096803274484 3.2102907342117746
+HD75387 154.6429930996287 -56.8586932030658 1.454870756038402
+HD75759 154.9597215172163 -56.33391163155214 2.140073113725566
+HD75821 159.3514105464216 -60.12605756898013 3.2841174265673043
+HD76161 162.0349527302479 -61.45211541917097 0.8466467129836728
+HD76566 159.171829221158 -58.42512270161932 0.987951910031594
+HD76805 168.9041506719922 -64.56778643893459 2.3751724463877486
+HD77002 180.8887318724844 -69.0790481272171 2.9925483933819033
+HD77464 168.3774558294834 -63.24571460949483 0.5
+HD78548 176.4975664727743 -65.82670478629494 1.0540209296031935
+HD78764 214.2391864310211 -73.02058095009407 3.0285049691825967
+HD79351 183.4169571780523 -67.52223460094062 3.550729873781159
+HD79447 190.8584700057938 -69.47356069208561 3.2674294200418164
+HD81188 178.8939943127057 -63.71664449988081 3.8720430840727054
+HD81848 177.4429883549566 -62.10396608054067 1.6606756814455261
+HD83058 176.4757215167776 -59.7111559763743 3.2408510541329014
+HD83183 188.7398508781064 -65.36946715601499 1.150197582732439
+HD83754 152.6776306658122 -26.5981592450739 2.072453600303152
+HD83953 157.0455095453033 -35.06945284946878 2.0704526701242623
+HD85871 186.2577408081183 -60.91067013355496 1.1403751194246121
+HD86118 191.2364411907885 -62.870679678706 1.6705982473769496
+HD86440 185.9463524535155 -59.94532380157827 2.618103956223811
+HD86606 219.5853676067188 -69.19179024302812 1.0158310077174846
+HD86612 161.7372421284581 -33.73900385113339 0.5
+HD87015 145.0621185623622 9.345162303849031 2.3878196171059796
+HD87901 149.8290206326514 0.4640074324609858 3.4678899459959514
+HD886 9.152389642157058 12.6009326683005 3.860264344904536
+HD88661 193.9195121751007 -60.95697581304692 2.190612035180768
+HD89080 217.4319127929379 -67.37662784153815 1.2715684634872797
+HD89890 192.7965654515135 -58.65629798992916 2.354154905174903
+HD90264 211.3572596758433 -65.23045579435151 1.4414383152144066
+HD90994 159.4994650750839 -9.319653389174215 1.4958006170698135
+HD91316 156.3882912493882 0.1490848606650997 3.3255408926423007
+HD91465 203.0543715651746 -61.44072434441311 3.4184446732257774
+HD92664 210.0480168977177 -62.7857192757208 0.5
+HD92938 209.2091916447879 -62.23875556153324 2.54237147172472
+HD93030 209.1841809670724 -62.1333909281327 3.926625091477544
+HD93194 208.6084645306387 -61.77222690070057 2.451104023327503
+HD93521 148.2860066646482 27.54612907141209 1.7349470553266066
+HD93549 209.448746052678 -61.74816203852298 0.5567209848044452
+HD93845 245.6413269942407 -67.7860539956461 3.244903843397782
+HD96088 203.0791327187383 -55.96467212660943 1.7765040212757903
+HD96446 205.9703190333487 -57.19592825000322 1.2051179982670883
+HD97991 171.3023563116765 -7.526387131905575 0.9268272705232764
+HD98718 202.192588121063 -51.80568254393103 3.2568861625344523
+HD99171 192.8046355892732 -41.8414022415711 2.1437348885155596
+HD99264 228.0753587039966 -63.20988147536961 0.661823290015131
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
new file mode 100644
index 0000000000..9614419d51
--- /dev/null
+++ b/imap_processing/glows/ancillary/imap_glows_pipeline-settings_20250923_v002.json
@@ -0,0 +1,54 @@
+{
+ "description": "Settings for ground-processing pipeline for IMAP/GLOWS instrument",
+ "version": "0.1",
+ "date_of_creation_yyyymmdd": "20230527",
+ "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-5
+ },
+ "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": 2.0
+ },
+ "active_bad_time_flags": {
+ "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": true,
+ "is_night": false,
+ "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": true,
+ "is_spin_period_difference_beyond_threshold": false
+ },
+ "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
+ },
+ "number_of_good_histograms_at_night": 3,
+ "l3a_nominal_number_of_bins": 90
+}
diff --git a/imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat b/imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat
new file mode 100644
index 0000000000..d7db27c18c
--- /dev/null
+++ b/imap_processing/glows/ancillary/imap_glows_suspected-transients_20250923_v002.dat
@@ -0,0 +1,10 @@
+# Description: list of transients for L1b defined by IMAP/GLOWS Instrument Team for ground-processing pipeline in the IMAP SDC
+# Value 1 in mask_array means that a given bin is suspected transient
+# version: 0.2
+# columns: l1b_unique_block_identifier, histogram_mask_array
+2013-09-08T09:46:14 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2013-09-08T09:48:14 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2014-09-08T19:15:01 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2014-09-08T19:17:01 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2015-06-06T17:58:00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+2015-06-06T18:00:00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
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 748dae7d05..6166f10490 100644
--- a/imap_processing/glows/l1b/glows_l1b.py
+++ b/imap_processing/glows/l1b/glows_l1b.py
@@ -1,23 +1,58 @@
"""Methods for processing GLOWS L1B data."""
import dataclasses
+import logging
import numpy as np
import xarray as xr
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 DirectEventL1B, HistogramL1B
-
-
-def glows_l1b(input_dataset: xr.Dataset) -> xr.Dataset:
+from imap_processing.glows.l1b.glows_l1b_data import (
+ AncillaryExclusions,
+ AncillaryParameters,
+ DirectEventL1B,
+ HistogramL1B,
+ PipelineSettings,
+)
+from imap_processing.spice.time import et_to_datetime64, ttj2000ns_to_et
+
+logger = logging.getLogger(__name__)
+
+
+def glows_l1b(
+ input_dataset: xr.Dataset,
+ excluded_regions: xr.Dataset,
+ 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.
+ uv_sources : xr.Dataset
+ Dataset containing UV sources (stars) with coordinates and masking radii. It is
+ the output from GlowsAncillaryCombiner.
+ suspected_transients : xr.Dataset
+ Dataset containing suspected transient signals with time-based masks. This is
+ the output from GlowsAncillaryCombiner.
+ 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
-------
@@ -28,29 +63,82 @@ def glows_l1b(input_dataset: xr.Dataset) -> xr.Dataset:
cdf_attrs.add_instrument_global_attrs("glows")
cdf_attrs.add_instrument_variable_attrs("glows", "l1b")
- logical_source = (
- input_dataset.attrs["Logical_source"][0]
- if isinstance(input_dataset.attrs["Logical_source"], list)
- else input_dataset.attrs["Logical_source"]
+ 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,
+ uv_sources=uv_sources,
+ suspected_transients=suspected_transients,
+ exclusions_by_instr_team=exclusions_by_instr_team,
+ )
+ pipeline_settings = PipelineSettings(
+ pipeline_settings_dataset.sel(epoch=day, method="nearest"),
)
- if "hist" in logical_source:
- output_dataset = create_l1b_hist_output(input_dataset, cdf_attrs)
+ ancillary_parameters = AncillaryParameters(conversion_table_dict)
- elif "de" in logical_source:
- output_dataset = create_l1b_de_output(input_dataset, cdf_attrs)
+ 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,
+ )
- else:
- raise ValueError(
- f"Logical_source {input_dataset.attrs['Logical_source']} for input file "
- f"does not match histogram "
- "('hist') or direct event ('de')."
- )
+ 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")
+ ]
return output_dataset
-def process_de(l1a: xr.Dataset) -> tuple[xr.DataArray]:
+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, ancillary_parameters: AncillaryParameters
+) -> tuple[xr.DataArray]:
"""
Will process the direct event data from the L1A dataset and return the L1B dataset.
@@ -64,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
-------
@@ -102,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,
@@ -114,7 +225,12 @@ def process_de(l1a: xr.Dataset) -> tuple[xr.DataArray]:
return l1b_fields
-def process_histogram(l1a: xr.Dataset) -> xr.Dataset:
+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.
@@ -128,6 +244,12 @@ def process_histogram(l1a: xr.Dataset) -> xr.Dataset:
----------
l1a : xr.Dataset
The L1A dataset to process.
+ ancillary_exclusions : AncillaryExclusions
+ 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
-------
@@ -135,6 +257,16 @@ def process_histogram(l1a: xr.Dataset) -> xr.Dataset:
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()]
@@ -149,6 +281,8 @@ def process_histogram(l1a: xr.Dataset) -> xr.Dataset:
"spacecraft_location_std_dev": ["ecliptic"],
"spacecraft_velocity_average": ["ecliptic"],
"spacecraft_velocity_std_dev": ["ecliptic"],
+ "spin_axis_orientation_average": ["latitudinal"],
+ "spin_axis_orientation_std_dev": ["latitudinal"],
"flags": ["flag_dim"],
}
@@ -161,12 +295,30 @@ def process_histogram(l1a: xr.Dataset) -> xr.Dataset:
]
# 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
+ def create_histogram_l1b(*args) -> tuple: # type: ignore[no-untyped-def]
+ """
+ Create HistogramL1B object with captured ancillary data.
+
+ Parameters
+ ----------
+ *args
+ Variable arguments passed from xr.apply_ufunc containing L1A data.
+
+ Returns
+ -------
+ tuple
+ Tuple of processed L1B data arrays from HistogramL1B.output_data().
+ """
+ return HistogramL1B( # type: ignore[call-arg]
+ *args, ancillary_exclusions, ancillary_parameters, pipeline_settings
+ ).output_data()
+
l1b_fields = xr.apply_ufunc(
- lambda *args: HistogramL1B(*args).output_data(),
+ create_histogram_l1b,
*dataarrays,
input_core_dims=input_dims,
output_core_dims=output_dims,
@@ -179,19 +331,30 @@ def process_histogram(l1a: xr.Dataset) -> xr.Dataset:
def create_l1b_hist_output(
- input_dataset: xr.Dataset, cdf_attrs: ImapCdfAttributes
+ l1b_dataarrays: tuple[xr.DataArray],
+ epoch: xr.DataArray,
+ bin_coord: xr.DataArray,
+ cdf_attrs: ImapCdfAttributes,
) -> 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.
@@ -200,7 +363,7 @@ def create_l1b_hist_output(
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(
@@ -230,8 +393,17 @@ def create_l1b_hist_output(
attrs=cdf_attrs.get_variable_attributes("ecliptic_attrs", check_schema=False),
)
+ latitudinal_data = xr.DataArray(
+ np.arange(2),
+ name="latitudinal",
+ dims=["latitudinal"],
+ attrs=cdf_attrs.get_variable_attributes(
+ "latitudinal_attrs", check_schema=False
+ ),
+ )
+
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),
@@ -244,8 +416,6 @@ def create_l1b_hist_output(
attrs=cdf_attrs.get_variable_attributes("bins_label", check_schema=False),
)
- output_dataarrays = process_histogram(input_dataset)
-
output_dataset = xr.Dataset(
coords={
"epoch": data_epoch,
@@ -254,27 +424,31 @@ def create_l1b_hist_output(
"bad_angle_flags": bad_flag_data,
"bad_time_flags": flag_data,
"ecliptic": eclipic_data,
+ "latitudinal": latitudinal_data,
},
attrs=cdf_attrs.get_global_attributes("imap_glows_l1b_hist"),
)
# 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.
@@ -285,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
-------
@@ -294,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 26e5516fee..7fcb18331c 100644
--- a/imap_processing/glows/l1b/glows_l1b_data.py
+++ b/imap_processing/glows/l1b/glows_l1b_data.py
@@ -1,28 +1,325 @@
"""Module for GLOWS L1B data products."""
import dataclasses
-import json
from dataclasses import InitVar, dataclass, field
-from pathlib import Path
-from typing import Optional
import numpy as np
+import xarray as xr
+from scipy.stats import circmean, circstd
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,
+ frame_transform,
+ get_instrument_mounting_az_el,
+ spherical_to_cartesian,
+)
+from imap_processing.spice.spin import (
+ get_instrument_spin_phase,
+ get_spin_angle,
+ get_spin_data,
+)
+from imap_processing.spice.time import met_to_datetime64, met_to_sclkticks, sct_to_et
+
+
+@dataclass
+class PipelineSettings: # numpydoc ignore=PR02
+ """
+ GLOWS L1B Pipeline Settings for controlling bad-angle and bad-time flag processing.
+
+ This class extracts pipeline settings from the JSON configuration file processed
+ through GlowsAncillaryCombiner.
+
+ Based on Section 3.12 of the GLOWS algorithm document, the pipeline settings
+ file contains parameters for the ground-processing pipeline including thresholds,
+ bad-time flags to be activated, bad-angle flags to be activated, and other
+ processing controls.
+
+ Parameters
+ ----------
+ pipeline_dataset : xr.Dataset
+ Dataset from GlowsAncillaryCombiner.combined_dataset containing the
+ pipeline settings data extracted from the JSON file.
+
+ Attributes
+ ----------
+ active_bad_angle_flags : list[bool]
+ Binary mask determining which of the 4 bad-angle flags are active:
+ [is_close_to_uv_source, is_inside_excluded_region,
+ is_excluded_by_instr_team, is_suspected_transient]
+ Default: All flags set to True (all active).
+
+ active_bad_time_flags : list[bool]
+ Binary mask determining which bad-time flags from onboard processing
+ should be used for quality control to identify "good time" L1B blocks.
+
+ sunrise_offset : float
+ Offset in hours to adjust sunrise time relative to onboard settings
+ for fine-tuning the day/night boundary determination.
+
+ sunset_offset : float
+ 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.
+
+ Notes
+ -----
+ Usage example:
+
+ .. code-block:: python
+
+ # Create combiner for pipeline settings file
+ pipeline_combiner = GlowsAncillaryCombiner(pipeline_settings_files, end_date)
+
+ # Create PipelineSettings object
+ pipeline_settings = PipelineSettings(pipeline_combiner.combined_dataset)
+
+ # Use the settings
+ if pipeline_settings.active_bad_angle_flags[0]: # is_close_to_uv_source
+ # Process UV source exclusions
+ pass
+ """
+
+ pipeline_dataset: InitVar[xr.Dataset]
+
+ # Extracted pipeline settings attributes
+ active_bad_angle_flags: list[bool] = field(init=False)
+ 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:
+ """
+ Extract pipeline settings from the dataset.
+
+ Parameters
+ ----------
+ pipeline_dataset : xr.Dataset
+ 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] * 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:
+ """
+ Organize input ancillary files for GLOWS L1B bad-angle flag processing.
+
+ This class holds the four types of ancillary datasets required for computing
+ bad-angle flags in GLOWS L1B histogram processing. All datasets should be
+ obtained from the GlowsAncillaryCombiner.combined_dataset property after
+ processing the respective ancillary files.
+
+ Attributes
+ ----------
+ excluded_regions : xr.Dataset
+ Dataset containing excluded sky regions with ecliptic coordinates.
+ Expected structure from GlowsAncillaryCombiner:
+ - 'ecliptic_longitude_deg': DataArray with dimension ('epoch', 'region')
+ - 'ecliptic_latitude_deg': DataArray with dimension ('epoch', 'region')
+
+ uv_sources : xr.Dataset
+ Dataset containing UV sources (stars) with coordinates and masking radii.
+ Expected structure from GlowsAncillaryCombiner:
+ - 'object_name': DataArray with dimension ('epoch', 'source')
+ - 'ecliptic_longitude_deg': DataArray with dimension ('epoch', 'source')
+ - 'ecliptic_latitude_deg': DataArray with dimension ('epoch', 'source')
+ - 'angular_radius_for_masking': DataArray with dimension ('epoch', 'source')
+
+ suspected_transients : xr.Dataset
+ Dataset containing suspected transient signals with time-based masks.
+ Expected structure from GlowsAncillaryCombiner:
+ - 'l1b_unique_block_identifier', dimensions ('epoch', 'time_block')
+ - 'histogram_mask_array', dimensions ('epoch', 'time_block')
+
+ exclusions_by_instr_team : xr.Dataset
+ Dataset containing manual exclusions by instrument team with time-based masks.
+ Expected structure from GlowsAncillaryCombiner:
+ - 'l1b_unique_block_identifier', dimensions ('epoch', 'time_block')
+ - 'histogram_mask_array', dimensions ('epoch', 'time_block')
+
+ Notes
+ -----
+ Usage example:
+
+ .. code-block:: python
+
+ # Create combiners for each ancillary file type
+ excluded_regions_combiner = GlowsAncillaryCombiner(
+ excluded_regions_files, end_date)
+ uv_sources_combiner = GlowsAncillaryCombiner(uv_sources_files, end_date)
+ suspected_transients_combiner = GlowsAncillaryCombiner(
+ suspected_transients_files, end_date)
+ exclusions_combiner = GlowsAncillaryCombiner(exclusions_files, end_date)
+
+ # Create AncillaryExclusions object
+ exclusions = AncillaryExclusions(
+ excluded_regions=excluded_regions_combiner.combined_dataset,
+ uv_sources=uv_sources_combiner.combined_dataset,
+ suspected_transients=suspected_transients_combiner.combined_dataset,
+ exclusions_by_instr_team=exclusions_combiner.combined_dataset
+ )
+
+ # Filter for a specific day using limit_by_day method
+ day_exclusions = exclusions.limit_by_day(np.datetime64('2025-09-23'))
+ """
+
+ excluded_regions: xr.Dataset
+ uv_sources: xr.Dataset
+ suspected_transients: xr.Dataset
+ exclusions_by_instr_team: xr.Dataset
+
+ def limit_by_day(self, day: np.datetime64) -> "AncillaryExclusions":
+ """
+ Return a new AncillaryExclusions object with data filtered for a specified day.
+
+ This method does not mutate the original object and can be called multiple times
+ with different days.
+
+ Parameters
+ ----------
+ day : np.datetime64
+ The day to filter data for.
+
+ Returns
+ -------
+ AncillaryExclusions
+ New instance with data filtered for the specified day.
+ """
+ return AncillaryExclusions(
+ excluded_regions=self.excluded_regions.sel(epoch=day, method="nearest"),
+ uv_sources=self.uv_sources.sel(epoch=day, method="nearest"),
+ suspected_transients=self.suspected_transients.sel(
+ epoch=day, method="nearest"
+ ),
+ exclusions_by_instr_team=self.exclusions_by_instr_team.sel(
+ epoch=day, method="nearest"
+ ),
+ )
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
----------
@@ -43,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"]
@@ -210,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.
@@ -218,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]
@@ -245,12 +560,13 @@ 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: Optional[np.ndarray] = field(init=False, default=None)
+ de_flags: np.ndarray | None = field(init=False, default=None)
# TODO: First two values of DE are sec/subsec
- direct_event_glows_times: Optional[np.ndarray] = field(init=False, default=None)
+ direct_event_glows_times: np.ndarray | None = field(init=False, default=None)
# 3rd value is pulse length
- direct_event_pulse_lengths: Optional[np.ndarray] = field(init=False, default=None)
+ direct_event_pulse_lengths: np.ndarray | None = field(init=False, default=None)
# TODO: where does the multi-event flag go?
def __post_init__(
@@ -268,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.
@@ -300,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)
@@ -315,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
)
@@ -392,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
@@ -464,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
@@ -490,26 +798,26 @@ 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)
- spin_period_ground_average: np.double = field(init=False) # retrieved from SPICE?
- spin_period_ground_std_dev: np.double = field(init=False) # retrieved from SPICE?
- position_angle_offset_average: np.double = field(init=False) # retrieved from SPICE
+ # These two are retrieved from spin data
+ spin_period_ground_average: np.double = field(init=False)
+ spin_period_ground_std_dev: np.double = field(init=False)
+ position_angle_offset_average: np.double = field(init=False) # from SPICE
position_angle_offset_std_dev: np.double = field(init=False) # from SPICE
- spin_axis_orientation_std_dev: np.double = field(init=False) # from SPICE
- spin_axis_orientation_average: np.double = field(init=False) # retrieved from SPICE
- spacecraft_location_average: np.ndarray = field(init=False) # retrieved from SPIC
- spacecraft_location_std_dev: np.ndarray = field(init=False) # retrieved from SPIC
- spacecraft_velocity_average: np.ndarray = field(init=False) # retrieved from SPIC
- spacecraft_velocity_std_dev: np.ndarray = field(init=False) # retrieved from SPIC
+ spin_axis_orientation_std_dev: np.ndarray = field(init=False) # from SPICE
+ spin_axis_orientation_average: np.ndarray = field(init=False) # from SPICE
+ spacecraft_location_average: np.ndarray = field(init=False) # from SPICE
+ spacecraft_location_std_dev: np.ndarray = field(init=False) # from SPICE
+ spacecraft_velocity_average: np.ndarray = field(init=False) # from SPICE
+ spacecraft_velocity_std_dev: np.ndarray = field(init=False) # from SPICE
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
@@ -519,6 +827,9 @@ def __post_init__(
hv_voltage_variance: np.double,
spin_period_variance: np.double,
pulse_length_variance: np.double,
+ ancillary_exclusions: AncillaryExclusions,
+ ancillary_parameters: AncillaryParameters,
+ pipeline_settings: PipelineSettings,
) -> None:
"""
Will process data.
@@ -535,62 +846,146 @@ def __post_init__(
Encoded spin period variance.
pulse_length_variance : numpy.double
Encoded pulse length variance.
+ ancillary_exclusions : AncillaryExclusions
+ 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)
- # TODO: These pieces will need to be filled in from SPICE kernels. For now,
- # they are placeholders. GLOWS example code has better placeholders if needed.
- self.spin_period_ground_average = np.double(-999.9)
- self.spin_period_ground_std_dev = np.double(-999.9)
- self.position_angle_offset_average = np.double(-999.9)
- self.position_angle_offset_std_dev = np.double(-999.9)
- self.spin_axis_orientation_std_dev = np.double(-999.9)
- self.spin_axis_orientation_average = np.double(-999.9)
- self.spacecraft_location_average = np.array([-999.9, -999.9, -999.9])
- self.spacecraft_location_std_dev = np.array([-999.9, -999.9, -999.9])
- self.spacecraft_velocity_average = np.array([-999.9, -999.9, -999.9])
- self.spacecraft_velocity_std_dev = np.array([-999.9, -999.9, -999.9])
- # Will require some additional inputs
- self.imap_spin_angle_bin_cntr = np.zeros((3600,))
+ # Add SPICE related variables
+ 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.
- 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_average = self.ancillary_parameters.decode(
+ self.filter_temperature_average = ancillary_parameters.decode(
"filter_temperature", self.filter_temperature_average
)
- self.filter_temperature_std_dev = self.ancillary_parameters.decode_std_dev(
+ self.filter_temperature_std_dev = ancillary_parameters.decode_std_dev(
"filter_temperature", filter_temperature_variance
)
- self.hv_voltage_average = self.ancillary_parameters.decode(
+ self.hv_voltage_average = ancillary_parameters.decode(
"hv_voltage", self.hv_voltage_average
)
- self.hv_voltage_std_dev = self.ancillary_parameters.decode_std_dev(
+ self.hv_voltage_std_dev = ancillary_parameters.decode_std_dev(
"hv_voltage", hv_voltage_variance
)
- self.spin_period_average = self.ancillary_parameters.decode(
+ self.spin_period_average = ancillary_parameters.decode(
"spin_period", self.spin_period_average
)
- self.spin_period_std_dev = self.ancillary_parameters.decode_std_dev(
+ self.spin_period_std_dev = ancillary_parameters.decode_std_dev(
"spin_period", spin_period_variance
)
- self.pulse_length_average = self.ancillary_parameters.decode(
+ self.pulse_length_average = ancillary_parameters.decode(
"pulse_length", self.pulse_length_average
)
- self.pulse_length_std_dev = self.ancillary_parameters.decode_std_dev(
+ self.pulse_length_std_dev = ancillary_parameters.decode_std_dev(
"pulse_length", pulse_length_variance
)
- self.histogram_flag_array = np.zeros((4, 3600), dtype=np.uint8)
- # 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)
+ # 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.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.
+
+ 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
+ data_end_met = np.double(self.imap_start_time) + np.double(
+ 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))
+
+ time_range = np.arange(data_start_time_et, data_end_time_et)
+
+ # Calculate spin period
+ # ---------------------
+ spin_data = get_spin_data()
+ # select spin data within the range from data start time to end time
+ spin_data = spin_data[
+ (spin_data["spin_start_met"] >= data_start_met)
+ & (spin_data["spin_start_met"] <= data_end_met)
+ ]
+
+ self.spin_period_ground_average = np.average(spin_data["spin_period_sec"])
+ self.spin_period_ground_std_dev = np.std(spin_data["spin_period_sec"])
+
+ # Calculate position angle offset
+ # --------------------------------
+ angle_offset = 360 - get_spin_angle(
+ get_instrument_spin_phase(
+ self.imap_start_time, instrument=geometry.SpiceFrame.IMAP_GLOWS
+ ),
+ degrees=True,
+ )
+ 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_spherical(
+ geometry.frame_transform(
+ time_range,
+ np.array([0, 0, 1]),
+ SpiceFrame.IMAP_SPACECRAFT,
+ SpiceFrame.ECLIPJ2000,
+ ),
+ )
+ # Calculate circular statistics for longitude (wraps around)
+ # 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)
+ # 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
+ # ------------------------------------------
+ # imap_state returns [x, y, z, vx, vy, vz].
+ # First three columns for position and last three for velocity.
+ imap_state = geometry.imap_state(
+ et=time_range, ref_frame=SpiceFrame.ECLIPJ2000, observer=SpiceBody.SUN
+ )
+ position = imap_state[:, :3]
+ velocity = imap_state[:, 3:]
+ # 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)
+ self.spacecraft_velocity_std_dev = np.std(velocity, axis=0)
def output_data(self) -> tuple:
"""
@@ -628,3 +1023,282 @@ 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:
+ """
+ Compute the histogram flag array for bad-angle flags.
+
+ Creates a (4, 3600) array where each row represents a different flag type:
+ - Row 0: is_close_to_uv_source
+ - Row 1: is_inside_excluded_region
+ - Row 2: is_excluded_by_instr_team
+ - Row 3: is_suspected_transient
+
+ Parameters
+ ----------
+ exclusions : AncillaryExclusions
+ Ancillary exclusions data filtered for the current day.
+
+ Returns
+ -------
+ np.ndarray
+ Array of shape (4, 3600) with bad-angle flags for each bin.
+ """
+ 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 a9cd181a66..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",
@@ -218,6 +163,13 @@ def create_l2_dataset(
"spacecraft_velocity_std_dev",
]
+ longitudinal_variables = [
+ "spin_axis_orientation_average",
+ "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(
@@ -225,13 +177,24 @@ def create_l2_dataset(
dims=["epoch", "ecliptic"],
attrs=attrs.get_variable_attributes(key),
)
+ elif key in longitudinal_variables:
+ output[key] = xr.DataArray(
+ value,
+ dims=["epoch", "latitudinal"],
+ attrs=attrs.get_variable_attributes(key),
+ )
elif key == "bad_time_flag_occurrences":
output[key] = xr.DataArray(
value,
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:
@@ -242,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 9659ab7b40..0d32cf775d 100644
--- a/imap_processing/hi/hi_l1a.py
+++ b/imap_processing/hi/hi_l1a.py
@@ -3,7 +3,6 @@
import logging
from collections import defaultdict
from pathlib import Path
-from typing import Union
import numpy as np
import xarray as xr
@@ -12,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
@@ -54,10 +44,52 @@
)
TOTAL_COUNTERS = ("a_total", "b_total", "c_total", "fee_de_recd", "fee_de_sent")
+# MEMDMP Packet definition of uint32 fields
+# 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": 10,
+ "coinc_length": 60,
+ "de_timetag": 65,
+ "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,
+ "cfd_dac_d": 85,
+ "de_mask": 87,
+ "ab_rnk": 89,
+ "cc_rnk": 90,
+ "ac_rnk": 91,
+ "bc_rnk": 92,
+ "abc_rnk": 93,
+ "acc_rnk": 94,
+ "bcc_rnk": 95,
+ "abcc_rnk": 96,
+ "esa_table": 100,
+ "esa_steps": 101,
+ "sci_cull": 106,
+ "eng_cull": 107,
+ "spins_per_step": 108,
+ "spins_per_de": 109,
+}
+
logger = logging.getLogger(__name__)
-def hi_l1a(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
+def hi_l1a(packet_file_path: str | Path) -> list[xr.Dataset]:
"""
Will process IMAP raw data to l1a.
@@ -95,6 +127,9 @@ def hi_l1a(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
elif apid_enum in [HIAPID.H45_DIAG_FEE, HIAPID.H90_DIAG_FEE]:
data = datasets_by_apid[apid]
gattr_key = "imap_hi_l1a_diagfee_attrs"
+ elif apid_enum in [HIAPID.H45_MEMDMP, HIAPID.H90_MEMDMP]:
+ data = finish_memdmp_dataset(datasets_by_apid[apid])
+ gattr_key = "imap_hi_l1a_memdmp_attrs"
# Update dataset global attributes
attr_mgr = ImapCdfAttributes()
@@ -111,7 +146,7 @@ def hi_l1a(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
def hi_packet_file_to_datasets(
- packet_file_path: Union[str, Path], use_derived_value: bool = False
+ packet_file_path: str | Path, use_derived_value: bool = False
) -> dict[int, xr.Dataset]:
"""
Extract hi datasets from packet file.
@@ -220,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",
@@ -246,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
@@ -313,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)
@@ -352,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(
@@ -445,3 +497,83 @@ def unpack_hist_counter(counter_bytes: bytes) -> NDArray[np.uint16]:
odd_uint12 = ((split_unit8 & (2**4 - 1)) << 8) + lower_uint8
output_array = np.column_stack((even_uint12, odd_uint12)).reshape(-1, 90)
return output_array
+
+
+def finish_memdmp_dataset(input_ds: xr.Dataset) -> xr.Dataset:
+ """
+ Create dataset for a number of Hi Memory Dump packets.
+
+ Parameters
+ ----------
+ input_ds : xarray.Dataset
+ Dataset of Hi-45 or Hi-90 MEMDMP packets generated using the
+ `imap_processing.utils.packet_file_to_datasets` function.
+
+ Returns
+ -------
+ dataset : xarray.Dataset
+ Dataset containing data from only MEMDMP packets generated upon entering
+ HVSCI. Specific memory items have been parsed out of the chunk of dumped
+ memory.
+ """
+ attr_mgr = ImapCdfAttributes()
+ attr_mgr.add_instrument_global_attrs(instrument="hi")
+ attr_mgr.add_instrument_variable_attrs(instrument="hi", level=None)
+
+ # We only care about the MEMDMP packets that are generated upon
+ # entry to HVSCI mode. This is very hacky, but the suggested way
+ # to identify these MEMDMP packets is to check that pktlen == 521
+ # Here, we remove packets where pktlen != 521
+ dataset = input_ds.where(input_ds["pkt_len"] == 521, drop=True)
+ logger.debug(
+ f"After trimming MEMDMP packets with pkt_len != 521,"
+ f"{dataset['epoch'].data.size} packets remain with a set"
+ f"of MEMORY_IDs = {set(dataset['memory_id'].data)}"
+ )
+
+ # Rename shcoarse variable (do this first since it copies the input_ds)
+ dataset = dataset.rename_vars({"shcoarse": "ccsds_met"})
+
+ dataset.epoch.attrs.update(
+ attr_mgr.get_variable_attributes("epoch", check_schema=False),
+ )
+
+ # Update existing variable attributes
+ for var_name in [
+ "version",
+ "type",
+ "sec_hdr_flg",
+ "pkt_apid",
+ "seq_flgs",
+ "src_seq_ctr",
+ "pkt_len",
+ "ccsds_met",
+ "cksum",
+ ]:
+ attrs = attr_mgr.get_variable_attributes(f"hi_hist_{var_name}")
+ dataset.data_vars[var_name].attrs.update(attrs)
+
+ new_vars = dict()
+ # Concatenate the dump_data from all packets into a single bytes string and
+ # interpret that bytes string as an array of uint32 values.
+ full_uint32_data = np.frombuffer(dataset["dump_data"].data.sum(), dtype=">u4")
+ # index_stride is the stride to traverse from packet to packet for a given
+ # item in the binary dump data.
+ index_stride = int(dataset["num_bytes"].data[0] // 4)
+ for new_var, offset in MEMDMP_DATA_INDS.items():
+ # The indices for each variable in the dump_data is the starting
+ # 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].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")
+ dataset.update(new_vars)
+
+ return dataset
diff --git a/imap_processing/hi/hi_l1b.py b/imap_processing/hi/hi_l1b.py
index a435105d97..a7a648eb53 100644
--- a/imap_processing/hi/hi_l1b.py
+++ b/imap_processing/hi/hi_l1b.py
@@ -3,22 +3,24 @@
import logging
from enum import IntEnum
from pathlib import Path
-from typing import Union
import numpy as np
+import pandas as pd
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 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,
+ EsaEnergyStepLookupTable,
HiConstants,
create_dataset_variables,
parse_sensor_number,
)
+from imap_processing.quality_flags import ImapHiL1bDeFlags
from imap_processing.spice.geometry import (
SpiceFrame,
instrument_pointing,
@@ -27,7 +29,7 @@
get_instrument_spin_phase,
get_spacecraft_spin_phase,
)
-from imap_processing.spice.time import met_to_sclkticks, sct_to_et
+from imap_processing.spice.time import met_to_sclkticks, met_to_utc, sct_to_et
from imap_processing.utils import packet_file_to_datasets
@@ -45,52 +47,7 @@ class TriggerId(IntEnum):
ATTR_MGR.add_instrument_variable_attrs(instrument="hi", level=None)
-def hi_l1b(dependency: Union[str, Path, xr.Dataset]) -> list[xr.Dataset]:
- """
- High level IMAP-HI L1B processing function.
-
- Parameters
- ----------
- dependency : str or xarray.Dataset
- Path to L0 file or L1A dataset to process.
-
- Returns
- -------
- l1b_dataset : list[xarray.Dataset]
- Processed xarray datasets.
- """
- # Housekeeping processing
- if isinstance(dependency, (Path, str)):
- logger.info(f"Running Hi L1B processing on file: {dependency}")
- l1b_datasets = housekeeping(dependency)
- elif isinstance(dependency, xr.Dataset):
- l1a_dataset = dependency
- logger.info(
- f"Running Hi L1B processing on dataset: "
- f"{l1a_dataset.attrs['Logical_source']}"
- )
- logical_source_parts = parse_filename_like(l1a_dataset.attrs["Logical_source"])
- # TODO: apid is not currently stored in all L1A data but should be.
- # Use apid to determine what L1B processing function to call
-
- # DE processing
- if logical_source_parts["descriptor"].endswith("de"):
- l1b_datasets = [annotate_direct_events(l1a_dataset)]
- l1b_datasets[0].attrs["Logical_source"] = (
- l1b_datasets[0]
- .attrs["Logical_source"]
- .format(sensor=logical_source_parts["sensor"])
- )
- else:
- raise NotImplementedError(
- f"No Hi L1B processing defined for file type: "
- f"{l1a_dataset.attrs['Logical_source']}"
- )
-
- return l1b_datasets
-
-
-def housekeeping(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
+def housekeeping(packet_file_path: str | Path) -> list[xr.Dataset]:
"""
Will process IMAP raw data to l1b housekeeping dataset.
@@ -108,6 +65,7 @@ def housekeeping(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
processed_data : list[xarray.Dataset]
Housekeeping datasets with engineering units.
"""
+ logger.info(f"Running Hi L1B processing on file: {packet_file_path}")
packet_def_file = (
imap_module_directory / "hi/packet_definitions/TLM_HI_COMBINED_SCI.xml"
)
@@ -137,37 +95,51 @@ def housekeeping(packet_file_path: Union[str, Path]) -> list[xr.Dataset]:
return datasets
-def annotate_direct_events(l1a_dataset: xr.Dataset) -> xr.Dataset:
+def annotate_direct_events(
+ l1a_de_dataset: xr.Dataset, l1b_hk_dataset: xr.Dataset, esa_energies_anc: Path
+) -> list[xr.Dataset]:
"""
Perform Hi L1B processing on direct event data.
Parameters
----------
- l1a_dataset : xarray.Dataset
+ l1a_de_dataset : xarray.Dataset
L1A direct event data.
+ l1b_hk_dataset : xarray.Dataset
+ L1B housekeeping data coincident with the L1A DE data.
+ esa_energies_anc : pathlib.Path
+ Location of the esa-energies ancillary csv file.
Returns
-------
- l1b_dataset : xarray.Dataset
- L1B direct event data.
+ l1b_datasets : list[xarray.Dataset]
+ List containing exactly one L1B direct event dataset.
"""
- l1b_dataset = l1a_dataset.copy()
- l1b_dataset.update(de_esa_energy_step(l1b_dataset))
- l1b_dataset.update(compute_coincidence_type_and_tofs(l1b_dataset))
- l1b_dataset.update(de_nominal_bin_and_spin_phase(l1b_dataset))
- l1b_dataset.update(compute_hae_coordinates(l1b_dataset))
- l1b_dataset.update(
+ logger.info(
+ f"Running Hi L1B processing on dataset: "
+ f"{l1a_de_dataset.attrs['Logical_source']}"
+ )
+
+ l1b_de_dataset = l1a_de_dataset.copy()
+ l1b_de_dataset.update(
+ de_esa_energy_step(l1b_de_dataset, l1b_hk_dataset, esa_energies_anc)
+ )
+ l1b_de_dataset.update(compute_coincidence_type_and_tofs(l1b_de_dataset))
+ l1b_de_dataset.update(de_nominal_bin_and_spin_phase(l1b_de_dataset))
+ l1b_de_dataset.update(compute_hae_coordinates(l1b_de_dataset))
+ l1b_de_dataset.update(
create_dataset_variables(
["quality_flag"],
- l1b_dataset["event_met"].size,
+ l1b_de_dataset["event_met"].size,
att_manager_lookup_str="hi_de_{0}",
)
)
- l1b_dataset = l1b_dataset.drop_vars(
+ 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",
@@ -179,8 +151,34 @@ def annotate_direct_events(l1a_dataset: xr.Dataset) -> xr.Dataset:
)
de_global_attrs = ATTR_MGR.get_global_attributes("imap_hi_l1b_de_attrs")
- l1b_dataset.attrs.update(**de_global_attrs)
- return l1b_dataset
+ l1b_de_dataset.attrs.update(**de_global_attrs)
+
+ logical_source_parts = parse_filename_like(l1a_de_dataset.attrs["Logical_source"])
+ l1b_de_dataset.attrs["Logical_source"] = l1b_de_dataset.attrs[
+ "Logical_source"
+ ].format(sensor=logical_source_parts["sensor"])
+ 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(
@@ -215,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
@@ -326,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
@@ -370,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,18 +397,20 @@ def compute_hae_coordinates(dataset: xr.Dataset) -> dict[str, xr.DataArray]:
return new_vars
-def de_esa_energy_step(dataset: xr.Dataset) -> dict[str, xr.DataArray]:
+def de_esa_energy_step(
+ l1b_de_ds: xr.Dataset, l1b_hk_ds: xr.Dataset, esa_energies_anc: Path
+) -> dict[str, xr.DataArray]:
"""
Compute esa_energy_step for each direct event.
- TODO: For now this function just returns the esa_step from the input dataset.
- Eventually, it will take L1B housekeeping data and determine the esa
- energy steps from that data.
-
Parameters
----------
- dataset : xarray.Dataset
+ l1b_de_ds : xarray.Dataset
The partial L1B dataset.
+ l1b_hk_ds : xarray.Dataset
+ L1B housekeeping data coincident with the L1A DE data.
+ esa_energies_anc : pathlib.Path
+ Location of the esa-energies ancillary csv file.
Returns
-------
@@ -407,10 +419,208 @@ def de_esa_energy_step(dataset: xr.Dataset) -> dict[str, xr.DataArray]:
"""
new_vars = create_dataset_variables(
["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="#")
+ esa_to_esa_energy_step_lut = get_esa_to_esa_energy_step_lut(
+ l1b_hk_ds, esa_energies_lut
+ )
+ new_vars["esa_energy_step"].values = esa_to_esa_energy_step_lut.query(
+ l1b_de_ds["ccsds_met"].data, l1b_de_ds["esa_step"].data
+ )
+
+ return new_vars
+
+
+def get_esa_to_esa_energy_step_lut(
+ l1b_hk_ds: xr.Dataset, esa_energies_lut: pd.DataFrame
+) -> EsaEnergyStepLookupTable:
+ """
+ Generate a lookup table that associates an esa_step to an esa_energy_step.
+
+ Parameters
+ ----------
+ l1b_hk_ds : xarray.Dataset
+ L1B housekeeping dataset.
+ esa_energies_lut : pandas.DataFrame
+ Esa energies lookup table derived from ancillary file.
+
+ Returns
+ -------
+ esa_energy_step_lut : EsaEnergyStepLookupTable
+ A lookup table object that can be used to query by MET time and esa_step
+ for the associated esa_energy_step values.
+
+ Notes
+ -----
+ Algorithm definition in section 2.1.2 of IMAP Hi Algorithm Document.
+ """
+ # Instantiate a lookup table object
+ esa_energy_step_lut = EsaEnergyStepLookupTable()
+ # Get the set of esa_steps visited
+ esa_steps = list(sorted(set(l1b_hk_ds["sci_esa_step"].data)))
+ # Break into contiguous segments where op_mode == "HVSCI"
+ # Pad the boolean array `op_mode == HVSCI` with False values on each end.
+ # This treats starting or ending in HVSCI mode as a transition in the next
+ # step where np.diff is used to find op_mode transitions into and out of
+ # HVSCI
+ padded_mask = np.pad(
+ l1b_hk_ds["op_mode"].data == "HVSCI", (1, 1), constant_values=False
+ )
+ mode_changes = np.diff(padded_mask.astype(int))
+ hsvsci_starts = np.nonzero(mode_changes == 1)[0]
+ hsvsci_ends = np.nonzero(mode_changes == -1)[0]
+ for i_start, i_end in zip(hsvsci_starts, hsvsci_ends, strict=False):
+ contiguous_hvsci_ds = l1b_hk_ds.isel(dict(epoch=slice(i_start, i_end)))
+ # Find median inner and outer ESA voltages for each ESA step
+ for esa_step in esa_steps:
+ single_esa_ds = contiguous_hvsci_ds.where(
+ contiguous_hvsci_ds["sci_esa_step"] == esa_step, drop=True
+ )
+ if len(single_esa_ds["epoch"].data) == 0:
+ logger.debug(
+ f"No instances of sci_esa_step == {esa_step} "
+ f"present in contiguous HVSCI block with interval: "
+ f"({met_to_utc(contiguous_hvsci_ds['shcoarse'].data[[0, -1]])})"
+ )
+ continue
+ inner_esa_voltage = np.where(
+ single_esa_ds["inner_esa_state"].data == "LO",
+ single_esa_ds["inner_esa_lo"].data,
+ single_esa_ds["inner_esa_hi"].data,
+ )
+ median_inner_esa = np.median(inner_esa_voltage)
+ median_outer_esa = np.median(single_esa_ds["outer_esa"].data)
+ # Match median voltages to ESA Energies LUT
+ inner_voltage_match = (
+ np.abs(median_inner_esa - esa_energies_lut["inner_esa_voltage"])
+ <= esa_energies_lut["inner_esa_delta_v"]
+ )
+ outer_voltage_match = (
+ np.abs(median_outer_esa - esa_energies_lut["outer_esa_voltage"])
+ <= esa_energies_lut["outer_esa_delta_v"]
+ )
+ matching_esa_energy = esa_energies_lut[
+ np.logical_and(inner_voltage_match, outer_voltage_match)
+ ]
+ if len(matching_esa_energy) != 1:
+ if len(matching_esa_energy) == 0:
+ logger.critical(
+ f"No esa_energy_step matches found for esa_step "
+ f"{esa_step} during interval: "
+ f"({met_to_utc(single_esa_ds['shcoarse'].data[[0, -1]])}) "
+ f"with median esa voltages: "
+ f"{median_inner_esa}, {median_outer_esa}."
+ )
+ if len(matching_esa_energy) > 1:
+ logger.critical(
+ f"Multiple esa_energy_step matches found for esa_step "
+ f"{esa_step} during interval: "
+ f"({met_to_utc(single_esa_ds['shcoarse'].data[[0, -1]])}) "
+ f"with median esa voltages: "
+ f"{median_inner_esa}, {median_outer_esa}."
+ )
+ continue
+ # Set LUT to matching esa_energy_step for time range
+ esa_energy_step_lut.add_entry(
+ contiguous_hvsci_ds["shcoarse"].data[0],
+ contiguous_hvsci_ds["shcoarse"].data[-1],
+ esa_step,
+ 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}",
)
- # TODO: Implement this algorithm
- new_vars["esa_energy_step"].values = dataset.esa_step.values
+
+ # 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 1636b7d4a4..c047ece1f0 100644
--- a/imap_processing/hi/hi_l2.py
+++ b/imap_processing/hi/hi_l2.py
@@ -2,182 +2,402 @@
import logging
from pathlib import Path
-from typing import Literal
import numpy as np
+import pandas as pd
import xarray as xr
-from imap_processing.ena_maps.ena_maps import HiPointingSet, RectangularSkyMap
-from imap_processing.spice.geometry import SpiceFrame
+from imap_processing.cdf.utils import load_cdf
+from imap_processing.ena_maps.ena_maps import (
+ 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).
"""
- # TODO: parse descriptor to determine map configuration
- sensor = "45" if "45" in descriptor else "90"
- direction: Literal["full"] = "full"
- cg_corrected = False
- map_spacing = 4
+ logger.info("Starting IMAP-Hi L2 processing pipeline")
+ logger.info(f"Descriptor: {descriptor}")
+ logger.info(f"Processing {len(psets)} pointing sets")
+
+ # 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'"
+ )
- rect_map = generate_hi_map(
+ logger.info(f"Step 1: Creating sky map from {len(psets)} pointing sets")
+ sky_maps = create_sky_map_from_psets(
psets,
- geometric_factors_path,
- esa_energies_path,
- direction=direction,
- cg_corrected=cg_corrected,
- map_spacing=map_spacing,
+ l2_ancillary_path_dict,
+ map_descriptor,
)
- # Get the map dataset with variables/coordinates in the correct shape
- # TODO get the correct descriptor and frame
- l2_ds = rect_map.build_cdf_dataset("hi", "l2", "sf", descriptor, sensor=sensor)
+ 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",
+ 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,
- cg_corrected: bool = False,
- direction: Literal["ram", "anti-ram", "full"] = "full",
- map_spacing: int = 4,
-) -> RectangularSkyMap:
+ l2_ancillary_path_dict: dict[str, Path],
+ descriptor: MapDescriptor,
+) -> dict[str, RectangularSkyMap]:
"""
- Project Hi PSET data into a rectangular sky map.
+ Project Hi PSET data into a sky map.
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.
- cg_corrected : bool, Optional
- Whether to apply Compton-Getting correction to the energies. Defaults to
- False.
- direction : str, Optional
- Apply filtering to PSET data include ram or anti-ram or full spin data.
- Defaults to "full".
- map_spacing : int, Optional
- Pixel spacing, in degrees, of the output map in degrees. Defaults to 4.
+ 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 : RectangularSkyMap
- 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.
"""
- rect_map = RectangularSkyMap(
- spacing_deg=map_spacing, spice_frame=SpiceFrame.ECLIPJ2000
+ 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)
+ }
+
+ 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,
+ )
- # TODO: Implement Compton-Getting correction
- if cg_corrected:
- raise NotImplementedError
- # TODO: Implement directional filtering
- if direction != "full":
- raise NotImplementedError
-
- for pset_path in psets:
- logger.info(f"Processing {pset_path}")
- pset = HiPointingSet(pset_path)
-
- # 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
- rect_map.project_pset_values_to_map(
- pset,
- ["counts", "exposure_factor", "bg_rates", "bg_rates_unc", "obs_date"],
+ 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)
)
- # 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:
- rect_map.data_1d[var] /= rect_map.data_1d["exposure_factor"]
+ return rect_maps
- rect_map.data_1d.update(calculate_ena_signal_rates(rect_map.data_1d))
- rect_map.data_1d.update(
- calculate_ena_intensity(
- rect_map.data_1d, geometric_factors_path, esa_energies_path
- )
+
+# =============================================================================
+# 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)
)
- rect_map.data_1d["obs_date"].data = rect_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)
- rect_map.data_1d["obs_date_range"] = xr.zeros_like(rect_map.data_1d["obs_date"])
-
- # Rename and convert coordinate from esa_energy_step energy
- # TODO: the correct conversion from esa_energy_step to esa_energy
- esa_energy_step_conversion = (np.arange(10, dtype=float) + 1) * 1000
- rect_map.data_1d = rect_map.data_1d.rename({"esa_energy_step": "energy"})
- rect_map.data_1d = rect_map.data_1d.assign_coords(
- energy=esa_energy_step_conversion[rect_map.data_1d["energy"].values]
+ map_ds["obs_date_range"] = xr.zeros_like(map_ds["obs_date"])
+
+ # 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"
)
- # Set the energy_step_delta values
- # TODO: get the correct energy delta values (they are set to NaN) in
- # rect_map.build_cdf_dataset()
- rect_map.data_1d = rect_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 rect_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
@@ -186,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.
@@ -211,51 +430,385 @@ 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]
+ )
+ energy_df = esa_energy_df(
+ l2_ancillary_path_dict["esa-energies"], map_ds["esa_energy_step"].data
)
- # TODO: Implement esa energies lookup
- if esa_energies_path:
- raise NotImplementedError
- esa_energy = xr.ones_like(map_ds["esa_energy_step"])
+ esa_energy = energy_df.to_xarray()["nominal_central_energy"]
# Convert ENA Signal Rate to Flux
- intensity_vars = {
- "ena_intensity": map_ds["ena_signal_rates"] / (geometric_factor * esa_energy),
- "ena_intensity_stat_unc": map_ds["ena_signal_rate_stat_unc"]
- / geometric_factor
- / esa_energy,
- "ena_intensity_sys_err": map_ds["bg_rates_unc"]
- / (geometric_factor * esa_energy),
- }
+ 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,
+ )
+
+ 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
)
- intensity_vars["ena_intensity_stat_unc"] = np.sqrt(
- (intensity_vars["ena_intensity_stat_unc"] ** 2).sum(dim="calibration_prod")
+
+ # 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
+ )
)
- intensity_vars["ena_intensity_sys_err"] = np.sqrt(
- (intensity_vars["ena_intensity_sys_err"] ** 2).sum(dim="calibration_prod")
+ # 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 intensity_vars
+ 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,
+ )
+ 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)
+
+
+# =============================================================================
+# SETUP AND INITIALIZATION HELPERS
+# =============================================================================
+
+
+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.
+
+ Parameters
+ ----------
+ esa_energies_path : str or pathlib.Path
+ Location of the calibration csv file containing the lookup data.
+ 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_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"
+ )
+ return esa_energies_lut.loc[esa_energy_steps]
diff --git a/imap_processing/hi/utils.py b/imap_processing/hi/utils.py
index 875985198c..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 Sequence
+from collections.abc import Generator, Iterable, Sequence
from dataclasses import dataclass
from enum import IntEnum
-from typing import Optional, Union
+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
@@ -15,11 +21,13 @@
class HIAPID(IntEnum):
"""Create ENUM for apid."""
+ H45_MEMDMP = 740
H45_APP_NHK = 754
H45_SCI_CNT = 769
H45_SCI_DE = 770
H45_DIAG_FEE = 772
+ H90_MEMDMP = 804
H90_APP_NHK = 818
H90_SCI_CNT = 833
H90_SCI_DE = 834
@@ -45,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
@@ -57,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
@@ -70,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:
"""
@@ -100,9 +159,9 @@ def parse_sensor_number(full_string: str) -> int:
def full_dataarray(
name: str,
attrs: dict,
- coords: Optional[dict[str, xr.DataArray]] = None,
- shape: Optional[Union[int, Sequence[int]]] = None,
- fill_value: Optional[float] = None,
+ coords: dict[str, xr.DataArray] | None = None,
+ shape: int | Sequence[int] | None = None,
+ fill_value: float | None = None,
) -> xr.DataArray:
"""
Generate an empty xarray.DataArray with appropriate attributes.
@@ -158,9 +217,9 @@ def full_dataarray(
def create_dataset_variables(
variable_names: list[str],
- variable_shape: Optional[Union[int, Sequence[int]]] = None,
- coords: Optional[dict[str, xr.DataArray]] = None,
- fill_value: Optional[float] = None,
+ variable_shape: int | Sequence[int] | None = None,
+ coords: dict[str, xr.DataArray] | None = None,
+ fill_value: float | None = None,
att_manager_lookup_str: str = "{0}",
) -> dict[str, xr.DataArray]:
"""
@@ -247,3 +306,780 @@ def detector_hit_str_to_int(detector_hit_str: str) -> int:
matches = re.findall(pattern, detector_hit_str)
# Sum the integer value assigned to the detector name for each match
return sum(CoincidenceBitmap[m] for m in matches)
+
+
+class EsaEnergyStepLookupTable:
+ """Class for holding a esa_step to esa_energy lookup table."""
+
+ def __init__(self) -> None:
+ self.df = pd.DataFrame(
+ {
+ "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
+
+ # Get the FILLVAL from the CDF attribute manager that will be returned
+ # for queries without matches
+ attr_mgr = ImapCdfAttributes()
+ attr_mgr.add_instrument_global_attrs("hi")
+ attr_mgr.add_instrument_variable_attrs(instrument="hi", level=None)
+ var_attrs = attr_mgr.get_variable_attributes(
+ "hi_de_esa_energy_step", check_schema=False
+ )
+ self._fillval = var_attrs["FILLVAL"]
+ self._esa_energy_step_dtype = var_attrs["dtype"]
+
+ def add_entry(
+ self, start_met: float, end_met: float, esa_step: int, esa_energy_step: int
+ ) -> None:
+ """
+ Add a single entry to the lookup table.
+
+ Parameters
+ ----------
+ start_met : float
+ Start mission elapsed time of the time range.
+ end_met : float
+ End mission elapsed time of the time range.
+ esa_step : int
+ ESA step value.
+ esa_energy_step : int
+ ESA energy step value to be stored.
+ """
+ new_row = pd.DataFrame(
+ {
+ "start_met": [start_met],
+ "end_met": [end_met],
+ "esa_step": [esa_step],
+ "esa_energy_step": [esa_energy_step],
+ }
+ )
+ self.df = pd.concat([self.df, new_row], ignore_index=True)
+ self._indexed = False
+
+ def _ensure_indexed(self) -> None:
+ """
+ Create index for faster queries if not already done.
+
+ Notes
+ -----
+ This method sorts the internal DataFrame by start_met and esa_step
+ for improved query performance.
+ """
+ if not self._indexed:
+ # Sort by start_met and esa_step for better query performance
+ self.df = self.df.sort_values(["start_met", "esa_step"]).reset_index(
+ drop=True
+ )
+ self._indexed = True
+
+ def query(
+ self,
+ query_met: float | Iterable[float],
+ esa_step: int | Iterable[float],
+ ) -> float | np.ndarray:
+ """
+ Query MET(s) and esa_step(s) to retrieve esa_energy_step(s).
+
+ Parameters
+ ----------
+ query_met : float or array_like
+ Mission elapsed time value(s) to query.
+ Can be a single float or array-like of floats.
+ esa_step : int or array_like
+ ESA step value(s) to match. Can be a single int or array-like of ints.
+ Must be same type (scalar or array-like) as query_met.
+
+ Returns
+ -------
+ float or numpy.ndarray
+ - If inputs are scalars: returns float (esa_energy_step)
+ - If inputs are array-like: returns numpy array of esa_energy_steps
+ with same length as inputs.
+ Contains FILLVAL for queries with no matches.
+
+ Raises
+ ------
+ ValueError
+ If one input is scalar and the other is array-like, or if both are
+ array-like but have different lengths.
+
+ Notes
+ -----
+ If multiple entries match a query, returns the first match found.
+ """
+ self._ensure_indexed()
+
+ # Check if inputs are scalars
+ is_scalar_met = np.isscalar(query_met)
+ is_scalar_step = np.isscalar(esa_step)
+
+ # Check for mismatched input types
+ if is_scalar_met != is_scalar_step:
+ raise ValueError(
+ "query_met and esa_step must both be scalars or both be array-like"
+ )
+
+ # Convert to arrays for uniform processing
+ query_mets = np.atleast_1d(query_met)
+ esa_steps = np.atleast_1d(esa_step)
+
+ # Ensure both arrays have the same shape
+ if query_mets.shape != esa_steps.shape:
+ raise ValueError(
+ "query_met and esa_step must have the same "
+ "length when both are array-like"
+ )
+
+ results = np.full_like(query_mets, self._fillval)
+
+ # Lookup esa_energy_steps for queries
+ for i, (qm, es) in enumerate(zip(query_mets, esa_steps, strict=False)):
+ mask = (
+ (self.df["start_met"] <= qm)
+ & (self.df["end_met"] >= qm)
+ & (self.df["esa_step"] == es)
+ )
+
+ matches = self.df[mask]
+ if not matches.empty:
+ results[i] = matches["esa_energy_step"].iloc[0]
+
+ # Return scalar for scalar inputs, array for array inputs
+ if is_scalar_met and is_scalar_step:
+ 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/constants.py b/imap_processing/hit/l0/constants.py
index 2ac855242a..1a64e361ca 100644
--- a/imap_processing/hit/l0/constants.py
+++ b/imap_processing/hit/l0/constants.py
@@ -114,6 +114,9 @@
# Define size of science frame (num of packets)
FRAME_SIZE = len(FLAG_PATTERN)
+# Mod 10 pattern
+MOD_10_PATTERN = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+
# Define the number of bits in the mantissa and exponent for
# decompressing data
MANTISSA_BITS = 12
diff --git a/imap_processing/hit/l0/decom_hit.py b/imap_processing/hit/l0/decom_hit.py
index 529e5a0b5f..357765c08a 100644
--- a/imap_processing/hit/l0/decom_hit.py
+++ b/imap_processing/hit/l0/decom_hit.py
@@ -260,12 +260,9 @@ def assemble_science_frames(sci_dataset: xr.Dataset) -> xr.Dataset:
height event data per valid science frame added as new
data variables.
"""
- # TODO: Figure out how to handle partial science frames at the
- # beginning and end of CCSDS files. These science frames are split
- # across CCSDS files and still need to be processed with packets
- # from the previous file. Only discard incomplete science frames
- # in the middle of the CCSDS file. The code currently skips all
- # incomplete science frames.
+ # TODO: The code currently skips all incomplete science frames.
+ # Only discard incomplete science frames in the middle of the CCSDS file or
+ # use fill values?
# Convert sequence flags and counters to NumPy arrays for vectorized operations
seq_flgs = sci_dataset.seq_flgs.values
@@ -289,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 50b2052d5b..7930195642 100644
--- a/imap_processing/hit/l1a/hit_l1a.py
+++ b/imap_processing/hit/l1a/hit_l1a.py
@@ -1,6 +1,8 @@
"""Decommutate HIT CCSDS data and create L1a data products."""
import logging
+from datetime import datetime
+from pathlib import Path
import numpy as np
import xarray as xr
@@ -19,6 +21,11 @@
ZENITH_ANGLES,
)
from imap_processing.hit.l0.decom_hit import decom_hit
+from imap_processing.spice.time import (
+ et_to_datetime64,
+ met_to_datetime64,
+ ttj2000ns_to_et,
+)
logger = logging.getLogger(__name__)
@@ -28,7 +35,7 @@
fillval = -9223372036854775808
-def hit_l1a(packet_file: str) -> list[xr.Dataset]:
+def hit_l1a(packet_file: Path, packet_date: str | None) -> list[xr.Dataset]:
"""
Will process HIT L0 data into L1A data products.
@@ -36,31 +43,42 @@ def hit_l1a(packet_file: str) -> list[xr.Dataset]:
----------
packet_file : str
Path to the CCSDS data packet file.
+ packet_date : str
+ The date of the packet data in 'YYYYMMDD' format. This is used to filter
+ data to the correct processing day since L0 will have a 20-minute
+ buffer before and after the processing day.
Returns
-------
processed_data : list[xarray.Dataset]
List of Datasets of L1A processed data.
"""
+ if not packet_date:
+ raise ValueError("Packet date is required for processing L1A data.")
+
# Unpack ccsds file to xarray datasets
- datasets_by_apid = get_datasets_by_apid(packet_file)
+ datasets_by_apid = get_datasets_by_apid(str(packet_file))
# Create the attribute manager for this data level
attr_mgr = get_attribute_manager("l1a")
- l1a_datasets = []
-
# Process l1a data products
+ l1a_datasets = []
if HitAPID.HIT_HSKP in datasets_by_apid:
logger.info("Creating HIT L1A housekeeping dataset")
- l1a_datasets.append(
- process_housekeeping_data(
- datasets_by_apid[HitAPID.HIT_HSKP], attr_mgr, "imap_hit_l1a_hk"
- )
+ hk_dataset = process_housekeeping_data(
+ datasets_by_apid[HitAPID.HIT_HSKP], attr_mgr, "imap_hit_l1a_hk"
+ )
+ # filter the housekeeping dataset to the processing day
+ hk_dataset = filter_dataset_to_processing_day(
+ hk_dataset, str(packet_date), epoch_vals=hk_dataset["epoch"].values
)
+ l1a_datasets.append(hk_dataset)
if HitAPID.HIT_SCIENCE in datasets_by_apid:
l1a_datasets.extend(
- process_science(datasets_by_apid[HitAPID.HIT_SCIENCE], attr_mgr)
+ process_science(
+ datasets_by_apid[HitAPID.HIT_SCIENCE], attr_mgr, str(packet_date)
+ )
)
return l1a_datasets
@@ -102,7 +120,15 @@ def subcom_sectorates(sci_dataset: xr.Dataset) -> xr.Dataset:
sci_dataset : xarray.Dataset
Xarray dataset with sectored rates data organized by species.
"""
- updated_dataset = sci_dataset.copy()
+ # Initialize the dataset with the required variables
+ updated_dataset = sci_dataset[
+ [
+ "sectorates",
+ "hdr_minute_cnt",
+ "livetime_counter",
+ "hdr_dynamic_threshold_state",
+ ]
+ ].copy(deep=True)
# Calculate mod 10 values
hdr_min_count_mod_10 = updated_dataset.hdr_minute_cnt.values % 10
@@ -124,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]
@@ -308,25 +336,270 @@ def add_cdf_attributes(
return dataset
+def find_complete_mod10_sets(mod_vals: np.ndarray) -> np.ndarray:
+ """
+ Find start indices where mod values match [0,1,2,3,4,5,6,7,8,9] pattern.
+
+ Parameters
+ ----------
+ mod_vals : np.ndarray
+ 1D array of mod 10 values from the hdr_minute_cnt field in the L1A counts data.
+
+ Returns
+ -------
+ np.ndarray
+ Indices in mod_vals where the complete pattern [0, 1, ..., 9] starts.
+ """
+ # The pattern to match is an array from 0-9
+ window_size = 10
+
+ if mod_vals.size < window_size:
+ logger.warning(
+ "Mod 10 array is smaller than the required window size for "
+ "pattern matching."
+ )
+ return np.array([], dtype=int)
+ # Use sliding windows to find pattern matches
+ sw_view = np.lib.stride_tricks.sliding_window_view(mod_vals, window_size)
+ matches = np.all(sw_view == np.arange(window_size), axis=1)
+ return np.where(matches)[0]
+
+
+def subset_sectored_counts(
+ sectored_counts_dataset: xr.Dataset, packet_date: str
+) -> xr.Dataset:
+ """
+ Subset data for complete sets of sectored counts and corresponding livetime values.
+
+ A set of sectored data starts with hydrogen and ends with iron and correspond to
+ the mod 10 values 0-9. The livetime values from the previous 10 minutes are used
+ to calculate the rates for each set since those counts are transmitted 10 minutes
+ after they were collected. Therefore, only complete sets of sectored counts where
+ livetime from the previous 10 minutes are available are included in the output.
+
+ Parameters
+ ----------
+ sectored_counts_dataset : xarray.Dataset
+ The sectored counts dataset.
+
+ packet_date : str
+ The date of the packet data in 'YYYYMMDD' format, used for filtering.
+
+ Returns
+ -------
+ xarray.Dataset
+ A dataset of complete sectored counts and corresponding livetime values
+ for the processing day.
+ """
+ # 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
+ # epoch dimension is filtered for complete sets.
+ sectored_counts_dataset = update_livetime_coord(sectored_counts_dataset)
+
+ # Identify 10-minute intervals of complete sectored counts
+ # by using the mod 10 values of the header minute counts.
+ # Mod 10 determines the species and energy bin the data belongs
+ # to. A mapping of mod 10 values to species and energy bins is
+ # provided in l0/constants.py for reference.
+ bin_size = 10
+ mod_10: np.ndarray = sectored_counts_dataset.hdr_minute_cnt.values % 10
+ start_indices = find_complete_mod10_sets(mod_10)
+
+ # Filter out start indices that are less than or equal to the bin size
+ # since the previous 10 minutes are needed for calculating rates
+ if start_indices.size == 0:
+ raise ValueError(
+ "No data to process - valid start indices not found for "
+ "complete sectored counts."
+ )
+ else:
+ start_indices = start_indices[start_indices >= bin_size]
+
+ # Subset data for complete sets of sectored counts.
+ # Each set of sectored counts is 10 minutes long, so we take the indices
+ # starting from the start indices and extending to the bin size of 10.
+ # This creates a 1D array of indices that correspond to the complete
+ # sets of sectored counts which is used to filter the L1A dataset and
+ # create the L1B sectored rates dataset.
+ data_indices = np.concatenate(
+ [np.arange(idx, idx + bin_size) for idx in start_indices]
+ )
+ complete_sectored_counts_dataset = sectored_counts_dataset.isel(epoch=data_indices)
+
+ 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)
+ ],
+ bin_size,
+ )
+
+ # Filter dataset for data in the processing day
+
+ # Trim the sectored data to epoch_per_complete_set values in the processing day
+ filtered_dataset = filter_dataset_to_processing_day(
+ complete_sectored_counts_dataset, packet_date, epoch_vals=epoch_per_complete_set
+ )
+
+ # Trim livetime to the size of the sectored data but shifted 10 minutes earlier.
+ filtered_dataset = subset_livetime(filtered_dataset)
+
+ return filtered_dataset
+
+
+def update_livetime_coord(sectored_dataset: xr.Dataset) -> xr.Dataset:
+ """
+ Update livetime_counter to use a new epoch coordinate.
+
+ Assign a new epoch coordinate to the `livetime_counter` variable.
+ This new coordinate is aligned with the original `epoch` dimension,
+ ensuring that `livetime_counter` remains unaffected when the original
+ `epoch` dimension is filtered for complete sets in `subset_sectored_counts`
+ function.
+
+ Parameters
+ ----------
+ sectored_dataset : xarray.Dataset
+ The dataset containing sectored counts and livetime_counter data.
+
+ Returns
+ -------
+ xarray.Dataset
+ The updated dataset with modified livetime_counter.
+ """
+ epoch_values = sectored_dataset.epoch.values
+ sectored_dataset = sectored_dataset.assign_coords(
+ {
+ "epoch_livetime": ("epoch", epoch_values),
+ }
+ )
+ da = sectored_dataset["livetime_counter"]
+ da = da.assign_coords(epoch_livetime=("epoch", epoch_values))
+
+ # Swap the dimension from 'epoch' to 'epoch_livetime'
+ da = da.swap_dims({"epoch": "epoch_livetime"})
+
+ # Update the dataset with the modified variable
+ sectored_dataset["livetime_counter"] = da
+
+ return sectored_dataset
+
+
+def subset_livetime(dataset: xr.Dataset) -> xr.Dataset:
+ """
+ Trim livetime to values shifted 10 minutes earlier than sectored data.
+
+ This ensures that the livetime values correspond to the sectored counts correctly
+ since sectored data is collected 10 minutes before it's transmitted.
+
+ Parameters
+ ----------
+ dataset : xarray.Dataset
+ The dataset containing sectored counts and livetime data.
+
+ Returns
+ -------
+ xarray.Dataset
+ The updated dataset with trimmed livetime data.
+ """
+ # epoch values are per science frame which is 1 minute
+ epoch_vals = dataset["epoch"].values
+ epoch_livetime_vals = dataset["epoch_livetime"].values
+
+ if not epoch_vals.size:
+ raise ValueError(
+ "Epoch values are empty. Cannot proceed with livetime subsetting."
+ )
+
+ # Get index positions of epoch[0] and epoch[-1] in epoch_livetime
+ start_idx = np.where(epoch_livetime_vals == epoch_vals[0])[0][0]
+ end_idx = np.where(epoch_livetime_vals == epoch_vals[-1])[0][0]
+
+ if start_idx < 10:
+ raise ValueError(
+ "Start index for livetime is less than 10. This indicates that the "
+ "dataset is too small to shift livetime correctly."
+ )
+
+ # Compute shifted indices by 10 minutes
+ start_trimmed = max(start_idx - 10, 0)
+ end_trimmed = max(end_idx - 10, 0)
+
+ return dataset.isel(epoch_livetime=slice(start_trimmed, end_trimmed + 1))
+
+
+def filter_dataset_to_processing_day(
+ dataset: xr.Dataset,
+ packet_date: str,
+ epoch_vals: np.ndarray,
+ sc_tick: bool = False,
+) -> xr.Dataset:
+ """
+ Filter the dataset for data within the processing day.
+
+ Parameters
+ ----------
+ dataset : xarray.Dataset
+ The dataset to filter.
+ packet_date : str
+ The date of the packet data in 'YYYYMMDD' format.
+ epoch_vals : np.ndarray
+ An array of epoch values. Used to identify indices of data that
+ belong in the processing day. For sectored counts data, an
+ array of mean epoch values for major frames (10 min. intervals)
+ is used to filter the dataset to ensure that major frames that span
+ midnight, but belong to the processing day, are included. For other
+ datasets, the dataset's epoch coordinate values will be used.
+ sc_tick : bool
+ If true, the dataset's sc_tick will be used to filter data as well.
+ This ensures that the ccsds headers that use sc_tick as a coordinate,
+ instead of epoch, also corresponds to the processing day.
+
+ Returns
+ -------
+ xarray.Dataset
+ The filtered dataset containing data within the processing day.
+ """
+ processing_day = datetime.strptime(packet_date, "%Y%m%d").strftime("%Y-%m-%d")
+
+ # Filter dataset by epoch indices in processing day
+ epoch_dt = et_to_datetime64(ttj2000ns_to_et(epoch_vals))
+ epoch_indices_in_processing_day = np.where(
+ epoch_dt.astype("datetime64[D]") == np.datetime64(processing_day)
+ )[0]
+ dataset = dataset.isel(epoch=epoch_indices_in_processing_day)
+
+ # If sc_tick is provided (coord for ccsds headers), filter by sc_tick too
+ if sc_tick:
+ sc_tick_dt = met_to_datetime64(dataset["sc_tick"].values)
+ indices_in_processing_day = np.where(
+ sc_tick_dt.astype("datetime64[D]") == np.datetime64(processing_day)
+ )[0]
+ dataset = dataset.isel(sc_tick=indices_in_processing_day)
+ return dataset
+
+
def process_science(
- dataset: xr.Dataset, attr_mgr: ImapCdfAttributes
+ dataset: xr.Dataset, attr_mgr: ImapCdfAttributes, packet_date: str
) -> list[xr.Dataset]:
"""
Will process science datasets for CDF products.
- Process binary science data for CDF creation. The data is
- grouped into science frames, decommutated and decompressed,
- and split into count rates and event datasets. Updates the
- dataset attributes and coordinates and data variable
- dimensions according to specifications in a cdf yaml file.
+ The function processes binary science data for CDF creation.
+ The data is decommutated, decompressed, grouped into science frames,
+ and split into count rates, sectored count rates, and event datasets.
+ It also updates the dataset attributes according to specifications
+ in a cdf yaml file.
Parameters
----------
dataset : xarray.Dataset
A dataset containing HIT science data.
-
attr_mgr : ImapCdfAttributes
Attribute manager used to get the data product field's attributes.
+ packet_date : str
+ The date of the packet data, used for processing.
Returns
-------
@@ -338,20 +611,37 @@ def process_science(
# Decommutate and decompress the science data
sci_dataset = decom_hit(dataset)
- # Organize sectored rates by species type
- sci_dataset = subcom_sectorates(sci_dataset)
+ # Create dataset for sectored data organized by species type
+ # 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)
+
+ # TODO:
+ # - headers are values per packet rather than per frame. Do these need to align
+ # with the science frames?
+ # For instance, the mean epoch for a frame that spans midnight might contain
+ # packets from the previous day but filtering sc_tick by processing day will
+ # exclude those packets. Is this an issue?
+
+ # Filter the science dataset to only include data from the processing day
+ sci_dataset = filter_dataset_to_processing_day(
+ sci_dataset, packet_date, epoch_vals=sci_dataset["epoch"].values, sc_tick=True
+ )
# Split the science data into count rates and event datasets
pha_raw_dataset = xr.Dataset(
{"pha_raw": sci_dataset["pha_raw"]}, coords={"epoch": sci_dataset["epoch"]}
)
- count_rates_dataset = sci_dataset.drop_vars("pha_raw")
+ count_rates_dataset = sci_dataset.drop_vars(["pha_raw", "sectorates"])
# Calculate uncertainties for count rates
count_rates_dataset = calculate_uncertainties(count_rates_dataset)
+ # sectored_count_rates_dataset = calculate_uncertainties(sectored_dataset)
l1a_datasets: dict = {
- "imap_hit_l1a_counts": count_rates_dataset,
+ "imap_hit_l1a_counts-standard": 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 b010ef3cec..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,
)
@@ -26,7 +25,7 @@
# TODO review logging levels to use (debug vs. info)
-def hit_l1b(dependencies: dict) -> list[xr.Dataset]:
+def hit_l1b(dependency: str | xr.Dataset, l1b_descriptor: str) -> xr.Dataset:
"""
Will process HIT data to L1B.
@@ -34,54 +33,56 @@ def hit_l1b(dependencies: dict) -> list[xr.Dataset]:
Parameters
----------
- dependencies : dict
- Dictionary of dependencies that are L1A xarray datasets
- for science data and a file path string to an L0 file
- for housekeeping data.
+ dependency : Union[str, xr.Dataset]
+ Dependency is either an L1A xarray dataset to process
+ science data or a file path string to an L0 file to
+ process housekeeping data.
+ l1b_descriptor : str
+ The descriptor for the L1B dataset to create.
Returns
-------
- processed_data : list[xarray.Dataset]
- List of four L1B datasets.
+ l1b_dataset : xarray.Dataset
+ The processed L1B dataset.
"""
# Create the attribute manager for this data level
attr_mgr = get_attribute_manager("l1b")
+ l1b_dataset = None
+
# Create L1B datasets
- l1b_datasets: list = []
- if "imap_hit_l0_raw" in dependencies:
+ if l1b_descriptor == "hk":
# Unpack ccsds file to xarray datasets
- packet_file = dependencies["imap_hit_l0_raw"]
+ packet_file = dependency
datasets_by_apid = get_datasets_by_apid(packet_file, derived=True)
- # TODO: update to raise error after all APIDs are included in the same
- # raw files. currently science and housekeeping are in separate files.
if HitAPID.HIT_HSKP in datasets_by_apid:
# Process housekeeping to L1B.
- l1b_datasets.append(
- process_housekeeping_data(
- datasets_by_apid[HitAPID.HIT_HSKP], attr_mgr, "imap_hit_l1b_hk"
- )
+ l1b_dataset = process_housekeeping_data(
+ datasets_by_apid[HitAPID.HIT_HSKP], attr_mgr, "imap_hit_l1b_hk"
)
logger.info("HIT L1B housekeeping dataset created")
- if "imap_hit_l1a_counts" in dependencies:
+ elif l1b_descriptor in ["standard-rates", "summed-rates", "sectored-rates"]:
# Process science data to L1B datasets
- l1a_counts_dataset = dependencies["imap_hit_l1a_counts"]
- l1b_datasets.extend(process_science_data(l1a_counts_dataset, attr_mgr))
- logger.info("HIT L1B science datasets created")
+ l1b_dataset = process_science_data(dependency, l1b_descriptor, attr_mgr)
+ logger.info("HIT L1B science dataset created")
+ else:
+ logger.error(f"Unsupported descriptor for L1B processing: {l1b_descriptor}")
+ raise ValueError(f"Unsupported descriptor: {l1b_descriptor}")
- return l1b_datasets
+ return l1b_dataset
def process_science_data(
- l1a_counts_dataset: xr.Dataset, attr_mgr: ImapCdfAttributes
-) -> list[xr.Dataset]:
+ l1a_counts_dataset: xr.Dataset, descriptor: str, attr_mgr: ImapCdfAttributes
+) -> xr.Dataset:
"""
Will create L1B science datasets for CDF products.
- Process L1A raw counts data to create L1B science data for
- CDF creation. This function will create three L1B science
+ This function processes L1A counts data to L1B science
+ data for CDF creation. There are three L1B science
datasets: standard rates, summed rates, and sectored rates.
- It will also update dataset attributes, coordinates and
+ This function creates one dataset based on the descriptor
+ provided. It will also update dataset attributes, coordinates and
data variable dimensions according to specifications in
a CDF yaml file.
@@ -89,46 +90,43 @@ def process_science_data(
----------
l1a_counts_dataset : xr.Dataset
The L1A counts dataset.
+ descriptor : str
+ The descriptor for the L1B dataset to create
+ (e.g., "standard-rates", "summed-rates", "sectored-rates").
attr_mgr : AttributeManager
The attribute manager for the L1B data level.
Returns
-------
- dataset : list
- The processed L1B science datasets as xarray datasets.
+ dataset : xarray.Dataset
+ A processed L1B science dataset.
"""
logger.info("Creating HIT L1B science datasets")
- # TODO: Write functions to create the following datasets
- # Process sectored rates dataset
+ dataset = None
+ logical_source = None
# Calculate fractional livetime from the livetime counter
- livetime = l1a_counts_dataset["livetime_counter"] / LIVESTIM_PULSES
- livetime = livetime.rename("livetime")
-
- # Process counts data to L1B datasets
- l1b_datasets: dict = {
- "imap_hit_l1b_standard-rates": process_standard_rates_data(
- l1a_counts_dataset, livetime
- ),
- "imap_hit_l1b_summed-rates": process_summed_rates_data(
- l1a_counts_dataset, livetime
- ),
- "imap_hit_l1b_sectored-rates": process_sectored_rates_data(
- l1a_counts_dataset, 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":
+ dataset = process_standard_rates_data(l1a_counts_dataset, livetime)
+ logical_source = "imap_hit_l1b_standard-rates"
+ elif descriptor == "summed-rates":
+ dataset = process_summed_rates_data(l1a_counts_dataset, livetime)
+ logical_source = "imap_hit_l1b_summed-rates"
+ elif descriptor == "sectored-rates":
+ dataset = process_sectored_rates_data(l1a_counts_dataset, livetime)
+ logical_source = "imap_hit_l1b_sectored-rates"
# Update attributes and dimensions
- for logical_source, dataset in l1b_datasets.items():
+ if dataset and logical_source:
dataset.attrs = attr_mgr.get_global_attributes(logical_source)
-
- # TODO: Add CDF attributes to yaml once they're defined for L1B science data
- # Assign attributes and dimensions to each data array in the Dataset
+ # TODO: Add CDF attributes to yaml
for field in dataset.data_vars.keys():
try:
- # Create a dict of dimensions using the DEPEND_I keys in the
- # attributes
+ # Create a dict of dimensions using the DEPEND_I keys in the attributes
dims = {
key: value
for key, value in attr_mgr.get_variable_attributes(field).items()
@@ -137,7 +135,6 @@ def process_science_data(
dataset[field].attrs = attr_mgr.get_variable_attributes(field)
dataset[field].assign_coords(dims)
except KeyError:
- print(f"Field {field} not found in attribute manager.")
logger.warning(f"Field {field} not found in attribute manager.")
# Skip schema check for epoch to prevent attr_mgr from adding the
@@ -145,10 +142,9 @@ def process_science_data(
dataset.epoch.attrs = attr_mgr.get_variable_attributes(
"epoch", check_schema=False
)
-
logger.info(f"HIT L1B dataset created for {logical_source}")
- return list(l1b_datasets.values())
+ return dataset
def initialize_l1b_dataset(l1a_counts_dataset: xr.Dataset, coords: list) -> xr.Dataset:
@@ -304,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)
@@ -359,79 +355,11 @@ def process_summed_rates_data(
return l1b_summed_rates_dataset
-def subset_data_for_sectored_counts(
- l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
-) -> tuple[xr.Dataset, xr.DataArray]:
- """
- Subset data for complete sets of sectored counts and corresponding livetime values.
-
- A set of sectored data starts with hydrogen and ends with iron and correspond to
- the mod 10 values 0-9. The livetime values from the previous 10 minutes are used
- to calculate the rates for each set since those counts are transmitted 10 minutes
- after they were collected. Therefore, only complete sets of sectored counts where
- livetime from the previous 10 minutes are available are included in the output.
-
- Parameters
- ----------
- l1a_counts_dataset : xr.Dataset
- The L1A counts dataset.
- livetime : xr.DataArray
- 1D array of livetime values calculated from the livetime counter.
-
- Returns
- -------
- tuple[xr.Dataset, xr.DataArray]
- Dataset of complete sectored counts and corresponding livetime values.
- """
- # Identify 10-minute intervals of complete sectored counts.
- bin_size = 10
- mod_10 = l1a_counts_dataset.hdr_minute_cnt.values % 10
- pattern = np.arange(bin_size)
-
- # Use sliding windows to find pattern matches
- matches = np.all(
- np.lib.stride_tricks.sliding_window_view(mod_10, bin_size) == pattern, axis=1
- )
- start_indices = np.where(matches)[0]
-
- # Filter out start indices that are less than or equal to the bin size
- # since the previous 10 minutes are needed for calculating rates
- if start_indices.size == 0:
- logger.error(
- "No data to process - valid start indices not found for "
- "complete sectored counts."
- )
- raise ValueError("No valid start indices found for complete sectored counts.")
- else:
- start_indices = start_indices[start_indices >= bin_size]
-
- # Subset data for complete sets of sectored counts.
- # Each set of sectored counts is 10 minutes long, so we take the indices
- # starting from the start indices and extend to the bin size of 10.
- # This creates a 1D array of indices that correspond to the complete
- # sets of sectored counts which is used to filter the L1A dataset and
- # create the L1B sectored rates dataset.
- data_indices = np.concatenate(
- [np.arange(idx, idx + bin_size) for idx in start_indices]
- )
- l1b_sectored_rates_dataset = l1a_counts_dataset.isel(epoch=data_indices)
-
- # Subset livetime values corresponding to the previous 10 minutes
- # for each start index. This ensures the livetime data aligns correctly
- # with the sectored counts for rate calculations.
- livetime_indices = np.concatenate(
- [np.arange(idx - bin_size, idx) for idx in start_indices]
- )
- livetime = livetime.isel(epoch=livetime_indices)
-
- return l1b_sectored_rates_dataset, livetime
-
-
def process_sectored_rates_data(
l1a_counts_dataset: xr.Dataset, livetime: xr.DataArray
) -> xr.Dataset:
"""
- Will process L1B sectored rates data from L1A raw counts data.
+ Will process L1A raw counts data into L1B sectored rates.
A complete set of sectored counts is taken over 10 science frames (10 minutes)
where each science frame contains counts for one species and energy range.
@@ -451,10 +379,13 @@ def process_sectored_rates_data(
rotation is split into 15 inclination ranges). See equation 11 in the algorithm
document.
+ NOTE: The L1A counts dataset has complete sets of sectored counts and livetime is
+ already shifted to 10 minutes before the counts. This was handled in L1A processing.
+
Parameters
----------
l1a_counts_dataset : xr.Dataset
- The L1A counts dataset.
+ The L1A counts dataset containing sectored counts.
livetime : xr.DataArray
1D array of livetime values calculated from the livetime counter.
@@ -477,11 +408,6 @@ def process_sectored_rates_data(
if any(str(var).startswith(f"{p}_") for p in particles)
]
- # Subset data for complete sets of sectored counts and corresponding livetime values
- l1a_counts_dataset, livetime = subset_data_for_sectored_counts(
- l1a_counts_dataset, livetime
- )
-
# Sum livetime over 10 minute intervals
livetime_10min = sum_livetime_10min(livetime)
@@ -537,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 cff9d3db5c..8c2230b214 100644
--- a/imap_processing/hit/l2/hit_l2.py
+++ b/imap_processing/hit/l2/hit_l2.py
@@ -27,16 +27,16 @@
# - review logging levels to use (debug vs. info)
-def hit_l2(dependency_sci: xr.Dataset, dependencies_anc: list) -> list[xr.Dataset]:
+def hit_l2(dependency_sci: xr.Dataset, dependencies_anc: list) -> xr.Dataset:
"""
- Will process HIT data to L2.
+ Will process HIT L1B data to L2.
Processes dependencies needed to create L2 data products.
Parameters
----------
dependency_sci : xr.Dataset
- L1B xarray science dataset that is either summed rates
+ L1B dataset that is either summed rates
standard rates or sector rates.
dependencies_anc : list
@@ -44,8 +44,8 @@ def hit_l2(dependency_sci: xr.Dataset, dependencies_anc: list) -> list[xr.Datase
Returns
-------
- processed_data : list[xarray.Dataset]
- List of one L2 dataset.
+ l2_dataset : xarray.Dataset
+ The processed L2 dataset from the dependency dataset provided.
"""
logger.info("Creating HIT L2 science dataset")
@@ -74,7 +74,7 @@ def hit_l2(dependency_sci: xr.Dataset, dependencies_anc: list) -> list[xr.Datase
logger.info(f"HIT L2 dataset created for {logical_source}")
- return [l2_dataset]
+ return l2_dataset
def add_cdf_attributes(
@@ -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
new file mode 100644
index 0000000000..e173c03748
--- /dev/null
+++ b/imap_processing/ialirt/calculate_ingest.py
@@ -0,0 +1,132 @@
+"""Packet ingest times and rates for each station."""
+
+import logging
+from datetime import datetime, timedelta, timezone
+from typing import Any
+
+logger = logging.getLogger(__name__)
+
+STATIONS = ["Kiel", "UKSA", "tlmrelay"]
+
+
+def packets_created(start_file_creation: datetime, lines: list) -> dict:
+ """
+ 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.
+ lines : list
+ All lines of log files.
+
+ Returns
+ -------
+ station_dict : dict
+ Timestamps and rates when packets were ingested.
+ """
+ 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 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",
+ )
+ .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)
+
+ return station_dict
+
+
+def format_ingest_data(last_filename: str, log_lines: list) -> dict:
+ """
+ Format packet ingest times and rates from log file.
+
+ Parameters
+ ----------
+ last_filename : str
+ Log file that is last chronologically.
+ log_lines : list[str]
+ Combined lines from all log files (assumed already sorted by time).
+
+ Returns
+ -------
+ realtime_summary : dict
+ Structured output with packet receipt info per station.
+
+ Notes
+ -----
+ Example output:
+ {
+ "summary": "I-ALiRT Real-time Ingest Summary",
+ "generated": "2025-08-07T21:36:09Z",
+ "time_format": "UTC (ISOC)",
+ "time_range": [
+ "2025-01-21T09:50:58Z",
+ "2025-01-21T09:55:58Z"
+ ],
+ "Kiel": {"last_data_received": ["2025-01-21T09:50:58Z", "2025-01-21T09:51:58Z"],
+ "rate_kbps": [2.0, 2.0]}
+ }
+ """
+ # File creation time.
+ last_timestamp_str = last_filename.split(".")[2]
+ last_timestamp_str = last_timestamp_str.replace("_", ":")
+ end_of_time = datetime.strptime(last_timestamp_str, "%Y-%jT%H:%M:%S")
+
+ # File creation time of last file minus 48 hrs.
+ start_of_time = datetime.strptime(last_timestamp_str, "%Y-%jT%H:%M:%S") - timedelta(
+ 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)",
+ "time_range": [
+ start_of_time.isoformat(),
+ end_of_time.isoformat(),
+ ], # Overall time range of the data
+ "stations": list(STATIONS),
+ **station_dict,
+ }
+
+ 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 d40168283b..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
@@ -33,10 +34,19 @@ class IalirtSwapiConstants:
boltz = 1.380649e-23 # Boltzmann constant, J/K
at_mass = 1.6605390666e-27 # atomic mass, kg
prot_mass = 1.007276466621 * at_mass # mass of proton, kg
- eff_area = 3.3e-5 * 1e-4 # effective area, meters squared
+ eff_area = 1.633e-4 * 1e-4 # effective area, cm2 to meters squared
az_fov = np.deg2rad(30) # azimuthal width of the field of view, radians
fwhm_width = 0.085 # FWHM of energy width
speed_ew = 0.5 * fwhm_width # speed width of energy passband
+ 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):
@@ -46,14 +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 Observatory staff.
+# 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 8131c87404..99bbc699d9 100644
--- a/imap_processing/ialirt/generate_coverage.py
+++ b/imap_processing/ialirt/generate_coverage.py
@@ -4,21 +4,85 @@
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
# Logger setup
logger = logging.getLogger(__name__)
-# TODO: get a list of all potential DSN stations.
-ALL_STATIONS = [*STATIONS.keys(), "DSS-55", "DSS-56", "DSS-74", "DSS-75"]
+ALL_STATIONS = [
+ "Kiel",
+ "DSS-24",
+ "DSS-25",
+ "DSS-26",
+ "DSS-34",
+ "DSS-35",
+ "DSS-36",
+ "DSS-53",
+ "DSS-54",
+ "DSS-55",
+ "DSS-56",
+ "DSS-74",
+ "DSS-75",
+ "DSS-43",
+]
+
+
+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)
-def generate_coverage(
+ 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.
@@ -31,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
-------
@@ -40,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"],
@@ -52,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:
@@ -63,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
+
+ schedule_mask = create_schedule_mask(station, time_range)
+ visible &= schedule_mask
- outage_mask = np.zeros(time_range.shape, dtype=bool)
+ 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)
@@ -87,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)
@@ -110,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 = (
@@ -118,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:
"""
@@ -56,7 +60,10 @@ def get_rotation_matrix(axis: NDArray, angle: NDArray) -> NDArray:
"""
angle_rad = np.radians(angle)
rot_matrices = np.array(
- [spice.axisar(z, float(phase)) for z, phase in zip(axis, angle_rad)]
+ [
+ spice.axisar(z, float(phase))
+ for z, phase in zip(axis, angle_rad, strict=False)
+ ]
)
return rot_matrices
@@ -95,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
@@ -120,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
@@ -130,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:
"""
@@ -166,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
@@ -184,8 +193,8 @@ def transform_instrument_vectors_to_inertial(
# Apply to instrument vectors
vectors = np.array(
[
- spice.mxv(rot.T.copy(), vec)
- for rot, vec in zip(total_rotations, instrument_vectors)
+ 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 54e02554b3..04efeeb56b 100644
--- a/imap_processing/ialirt/l0/parse_mag.py
+++ b/imap_processing/ialirt/l0/parse_mag.py
@@ -2,18 +2,24 @@
import logging
from decimal import Decimal
-from typing import Union
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,
+)
from imap_processing.ialirt.l0.mag_l0_ialirt_data import (
Packet0,
Packet1,
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 (
@@ -21,8 +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.spice.time import met_to_ttj2000ns, met_to_utc
+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, ttj2000ns_to_et
logger = logging.getLogger(__name__)
@@ -75,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
@@ -195,7 +207,7 @@ def get_time(
(grouped_data["group"] == group).values
][pkt_counter == 2]
- time_data: dict[str, Union[int, float]] = {
+ time_data: dict[str, int | float] = {
"pri_coarsetm": int(pri_coarsetm.item()),
"pri_fintm": int(pri_fintm.item()),
"sec_coarsetm": int(sec_coarsetm.item()),
@@ -204,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
)
@@ -260,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
@@ -290,7 +304,6 @@ def calculate_l1b(
def calibrate_and_offset_vectors(
vectors: np.ndarray,
- range_vals: np.ndarray,
calibration: np.ndarray,
offsets: np.ndarray,
is_magi: bool = False,
@@ -301,9 +314,7 @@ def calibrate_and_offset_vectors(
Parameters
----------
vectors : np.ndarray
- Raw magnetic vectors, shape (n, 3).
- range_vals : np.ndarray
- Range indices for each vector, shape (n). Values 0β3.
+ Raw magnetic vectors, shape (n, 4).
calibration : np.ndarray
Calibration matrix, shape (3, 3, 4).
offsets : np.ndarray
@@ -319,11 +330,9 @@ def calibrate_and_offset_vectors(
calibrated_and_offset_vectors : np.ndarray
Calibrated and offset vectors, shape (n, 3).
"""
- # Append range as 4th column
- vec_plus_range = np.concatenate((vectors, range_vals[:, np.newaxis]), axis=1)
-
# Apply calibration matrix -> (n,4)
- calibrated = MagL2L1dBase.apply_calibration(vec_plus_range, calibration)
+ # apply_calibration_offset_single_vector
+ calibrated = MagL2L1dBase.apply_calibration(vectors.reshape(1, 4), calibration)
# Apply offsets per vector
# vec shape (4)
@@ -338,9 +347,247 @@ def calibrate_and_offset_vectors(
return calibrated[:, :3]
+def apply_gradiometry_correction(
+ mago_vectors_eclipj2000: np.ndarray,
+ mago_time_data: np.ndarray,
+ magi_vectors_eclipj2000: np.ndarray,
+ magi_time_data: np.ndarray,
+ gradiometer_factor: np.ndarray,
+) -> tuple[np.ndarray, np.ndarray]:
+ """
+ Align MAGi to MAGo timestamps and apply gradiometry correction.
+
+ Parameters
+ ----------
+ mago_vectors_eclipj2000 : np.ndarray
+ MAGo vectors in inertial frame, shape (N, 3).
+ mago_time_data : np.ndarray
+ Time for primary sensor, shape (N, 3).
+ magi_vectors_eclipj2000 : np.ndarray
+ MAGi vectors in inertial frame, shape (M, 3).
+ magi_time_data : np.ndarray
+ Time for secondary sensor, shape (N, 3).
+ gradiometer_factor : np.ndarray
+ A (3,3) element matrix to scale and rotate the gradiometer offsets.
+
+ Returns
+ -------
+ mago_corrected : np.ndarray
+ Corrected MAGo vectors in inertial frame, shape (N, 3).
+ magnitude : np.ndarray
+ Magnitude of corrected MAGo vectors, shape (N,).
+ """
+ gradiometry_offsets = MagL1d.calculate_gradiometry_offsets(
+ mago_vectors_eclipj2000,
+ mago_time_data,
+ magi_vectors_eclipj2000,
+ magi_time_data,
+ )
+ mago_corrected = MagL1d.apply_gradiometry_offsets(
+ gradiometry_offsets, mago_vectors_eclipj2000, gradiometer_factor
+ )
+ magnitude = np.linalg.norm(mago_corrected, axis=-1).squeeze()
+
+ 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,
+ sc_inertial_decline: np.ndarray,
+ attitude_time: np.ndarray,
+ target_time: float,
+ mag_vector: np.ndarray,
+ instrument_frame: SpiceFrame,
+) -> np.ndarray:
+ """
+ Transform vector to ECLIPJ2000.
+
+ Parameters
+ ----------
+ sc_spin_phase_rad : numpy.ndarray
+ Spin phase for 4 packets 0 to 2Ο radians, shape (4).
+ sc_inertial_right : numpy.ndarray
+ Inertial right ascension for 4 packets 0 to 2Ο radians, shape (4).
+ sc_inertial_decline : numpy.ndarray
+ Inertial declination for 4 packets -Ο/2 to Ο/2 radians, 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'].
+ mag_vector : numpy.ndarray
+ Vector, shape (3).
+ instrument_frame : SpiceFrame
+ SPICE frame of the instrument.
+
+ Returns
+ -------
+ inertial_vector : np.ndarray
+ Transformed vector in the ECLIPJ2000 frame, shape (3,).
+
+ Notes
+ -----
+ The MAG vectors are calculated based on 4 packets,
+ each of which contains its own spin phase,
+ inertial right ascension, and inertial decline.
+ """
+ if target_time < attitude_time.min() or target_time > attitude_time.max():
+ logger.warning(
+ f"target_time {target_time} is outside attitude_time bounds "
+ f"[{attitude_time.min()}, {attitude_time.max()}]; using edge values."
+ )
+
+ # Get sort order based on attitude_time
+ sort_idx = np.argsort(attitude_time)
+
+ # Sort all arrays accordingly
+ attitude_time = attitude_time[sort_idx]
+ sc_spin_phase_rad = sc_spin_phase_rad[sort_idx]
+ sc_inertial_right = sc_inertial_right[sort_idx]
+ sc_inertial_decline = sc_inertial_decline[sort_idx]
+
+ 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,
+ )
+
+ # Transform each into ECLIPJ2000
+ inertial_vector = transform_instrument_vectors_to_inertial(
+ np.asarray(mag_vector).reshape(1, 3),
+ np.array([spin_phase_deg]),
+ np.array([ra_deg]),
+ np.array([dec_deg]),
+ instrument_frame,
+ )[0]
+
+ return inertial_vector
+
+
+def transform_to_frames(
+ target_time: np.ndarray,
+ inertial_vector: np.ndarray,
+) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
+ """
+ Transform vector to different frames.
+
+ Parameters
+ ----------
+ target_time : np.ndarray
+ Time at which to apply the transformation.
+ Will be primary_epoch (mago vector).
+ Example: time_data['primary_epoch'].
+ inertial_vector : np.ndarray
+ Transformed vector in the ECLIPJ2000 frame, shape (3,).
+
+ Returns
+ -------
+ gse_vector : np.ndarray
+ Transformed vector in the GSE frame, shape (3,).
+ gsm_vector : np.ndarray
+ Transformed vector in the GSM frame, shape (3,).
+ rtn_vector : np.ndarray
+ Transformed vector in the RTN frame, shape (3,).
+ """
+ et_target_time = ttj2000ns_to_et(target_time)
+
+ gse_vector = frame_transform(
+ et_target_time, inertial_vector, SpiceFrame.ECLIPJ2000, SpiceFrame.IMAP_GSE
+ )
+ gsm_vector = frame_transform(
+ et_target_time, inertial_vector, SpiceFrame.ECLIPJ2000, SpiceFrame.IMAP_GSM
+ )
+ rtn_vector = frame_transform(
+ et_target_time, inertial_vector, SpiceFrame.ECLIPJ2000, SpiceFrame.IMAP_RTN
+ )
+
+ return gse_vector, gsm_vector, rtn_vector
+
+
def process_packet(
- accumulated_data: xr.Dataset, calibration_dataset: xr.Dataset
-) -> tuple[list[dict], list[dict]]:
+ accumulated_data: xr.Dataset,
+ engineering_calibration_dataset: xr.Dataset,
+ l1d_calibration_dataset: xr.Dataset,
+) -> list[dict]:
"""
Parse the MAG packets.
@@ -348,8 +595,10 @@ def process_packet(
----------
accumulated_data : xr.Dataset
Packets dataset accumulated over 1 min.
- calibration_dataset : xr.Dataset
- Calibration dataset.
+ engineering_calibration_dataset : xr.Dataset
+ Engineering calibration dataset.
+ l1d_calibration_dataset : xr.Dataset
+ L1D calibration dataset.
Returns
-------
@@ -372,11 +621,29 @@ 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"])
- l1b_data = []
mag_data = []
+ met_all = []
+ mago_vectors_all = []
+ mago_times_all = []
+ magi_vectors_all = []
+ magi_times_all = []
+ incomplete_groups = []
for group in unique_groups:
# Get status values for each group.
@@ -388,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.
@@ -412,7 +676,7 @@ def process_packet(
pkt_counter,
science_data,
status_data,
- calibration_dataset,
+ engineering_calibration_dataset,
)
# Note: primary = MAGo, secondary = MAGi.
@@ -423,41 +687,126 @@ def process_packet(
if status_data["sec_isvalid"] == 0:
updated_vector_magi = np.full(4, -32768)
- science_data.update(
- {
- "calibrated_pri_x": updated_vector_mago[0],
- "calibrated_pri_y": updated_vector_mago[1],
- "calibrated_pri_z": updated_vector_mago[2],
- "calibrated_sec_x": updated_vector_magi[0],
- "calibrated_sec_y": updated_vector_magi[1],
- "calibrated_sec_z": updated_vector_magi[2],
- }
+ 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
+ )
+ magi_out = calibrate_and_offset_vectors(
+ updated_vector_magi, magi_calibration, offsets, is_magi=True
)
- l1b_data.append({**status_data, **science_data, **time_data})
+ # Convert to ECLIPJ2000 frame.
+ mago_inertial_vector = transform_to_inertial(
+ sc_spin_phase_rad.values,
+ sc_inertial_right.values,
+ sc_inertial_decline.values,
+ attitude_time,
+ time_data["primary_epoch"],
+ mago_out,
+ ValidFrames.MAGO.spice_frame,
+ )
+ magi_inertial_vector = transform_to_inertial(
+ sc_spin_phase_rad.values,
+ sc_inertial_right.values,
+ sc_inertial_decline.values,
+ attitude_time,
+ time_data["secondary_epoch"],
+ magi_out,
+ ValidFrames.MAGI.spice_frame,
+ )
- # Placeholder for real data.
met = grouped_data["met"][(grouped_data["group"] == group).values]
+ 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"].squeeze(),
+ )
+
+ gse_vector, gsm_vector, rtn_vector = transform_to_frames(
+ np.array(mago_times_all), mago_corrected
+ )
+
+ spherical = cartesian_to_spherical(gsm_vector)
+ phi_gsm = spherical[:, 1]
+ theta_gsm = spherical[:, 2]
+
+ spherical = cartesian_to_spherical(gse_vector)
+ phi_gse = spherical[:, 1]
+ theta_gse = spherical[:, 2]
+
+ # Omit the first value since we expect it to be extrapolated.
+ for i in range(len(mago_corrected)):
+ if i == 0:
+ continue
+
mag_data.append(
- {
- "apid": 478,
- "met": int(met.values.min()),
- "met_in_utc": met_to_utc(met.values.min()).split(".")[0],
- "ttj2000ns": int(met_to_ttj2000ns(met.values.min())),
- # TODO: Placeholder for mag_epoch
- "mag_epoch": int(met.values.min()),
- "mag_B_GSE": [Decimal("0.0") for _ in range(3)],
- "mag_B_GSM": [Decimal("0.0") for _ in range(3)],
- "mag_B_RTN": [Decimal("0.0") for _ in range(3)],
- "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"),
+ _populate_instrument_header_items(met_all[i])
+ | {
+ "instrument": "mag",
+ "mag_epoch": int(mago_times_all[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"]),
+ },
}
)
- return mag_data, l1b_data
+ return mag_data
def retrieve_matrix_from_single_l1b_calibration(
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 62dc80502e..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__)
@@ -91,18 +95,20 @@ def create_l1(
fast_rate_1_dict = {
prefix: value
for prefix, value in zip(
- HIT_PREFIX_TO_RATE_TYPE["FAST_RATE_1"], fast_rate_1.data
+ HIT_PREFIX_TO_RATE_TYPE["FAST_RATE_1"], fast_rate_1.data, strict=False
)
}
fast_rate_2_dict = {
prefix: value
for prefix, value in zip(
- HIT_PREFIX_TO_RATE_TYPE["FAST_RATE_2"], fast_rate_2.data
+ HIT_PREFIX_TO_RATE_TYPE["FAST_RATE_2"], fast_rate_2.data, strict=False
)
}
slow_rate_dict = {
prefix: value
- for prefix, value in zip(HIT_PREFIX_TO_RATE_TYPE["SLOW_RATE"], slow_rate.data)
+ for prefix, value in zip(
+ HIT_PREFIX_TO_RATE_TYPE["SLOW_RATE"], slow_rate.data, strict=False
+ )
}
l1 = {**fast_rate_1_dict, **fast_rate_2_dict, **slow_rate_dict}
@@ -125,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)
@@ -139,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
@@ -146,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
]
@@ -161,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 cb6dcc7b19..1be0277d38 100644
--- a/imap_processing/ialirt/l0/process_swapi.py
+++ b/imap_processing/ialirt/l0/process_swapi.py
@@ -2,7 +2,6 @@
import logging
from decimal import Decimal
-from typing import Optional
import numpy as np
import pandas as pd
@@ -10,16 +9,20 @@
from scipy.optimize import curve_fit
from scipy.special import erf
-from imap_processing import imap_module_directory
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 TIME_PER_BIN
+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
@@ -54,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)))
@@ -70,8 +76,8 @@ def count_rate(
def optimize_pseudo_parameters(
count_rates: np.ndarray,
count_rate_error: np.ndarray,
- energy_passbands: Optional[np.ndarray] = None,
-) -> (dict)[str, list[float]]:
+ energy_passbands: np.ndarray,
+) -> np.ndarray:
"""
Find the pseudo speed (u), density (n) and temperature (T) of solar wind particles.
@@ -84,61 +90,123 @@ def optimize_pseudo_parameters(
count_rate_error : np.ndarray
Standard deviation of the coincidence count rates parameter.
energy_passbands : np.ndarray, default None
- Energy passbands, passed in only for testing purposes.
+ Energy values, taken from the SWAPI lookup table.
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.
"""
- if not energy_passbands:
- # Read in energy passbands
- energy_data = pd.read_csv(
- f"{imap_module_directory}/tests/swapi/lut/imap_swapi_esa-unit"
- f"-conversion_20250626_v001.csv"
- )
- energy_passbands = (
- energy_data["Energy"][0:63]
- .replace(",", "", regex=True)
- .to_numpy()
- .astype(float)
- )
+ # 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
- # Initial guess pulled from page 52 of the IMAP SWAPI Instrument Algorithms Document
- initial_param_guess = np.array([550, 5.27, 1e5])
- 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 6 points surrounding it (inclusive)
- max_index = np.argmax(current_sweep_count_rates)
- sol = curve_fit(
+ 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
-def process_swapi_ialirt(unpacked_data: xr.Dataset) -> list[dict]:
+ 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(
+ unpacked_data: xr.Dataset, calibration_lut_table: pd.DataFrame
+) -> list[dict]:
"""
Extract I-ALiRT variables and calculate coincidence count rate.
@@ -146,6 +214,8 @@ def process_swapi_ialirt(unpacked_data: xr.Dataset) -> list[dict]:
----------
unpacked_data : xr.Dataset
SWAPI I-ALiRT data that has been parsed from the spacecraft packet.
+ calibration_lut_table : pd.DataFrame
+ DataFrame containing the contents of the SWAPI esa-unit-conversion lookup table.
Returns
-------
@@ -162,7 +232,17 @@ def process_swapi_ialirt(unpacked_data: xr.Dataset) -> list[dict]:
# 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")
@@ -177,42 +257,112 @@ def process_swapi_ialirt(unpacked_data: xr.Dataset) -> list[dict]:
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 / TIME_PER_BIN
- count_rate_error = np.sqrt(raw_coin_count) / TIME_PER_BIN
+ 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
+ ]
+
+ # 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)
+ )
+
+ pseudo_speed, pseudo_density, pseudo_temperature = optimize_pseudo_parameters(
+ raw_coin_rate.squeeze(), count_rate_error.squeeze(), energy_passbands
+ )
- solution = optimize_pseudo_parameters(raw_coin_rate, count_rate_error)
+ 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:],
+ )
- swapi_data = []
+ 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
+ )
- 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_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 5c3af674a5..8ae2e390e3 100644
--- a/imap_processing/ialirt/process_ephemeris.py
+++ b/imap_processing/ialirt/process_ephemeris.py
@@ -8,22 +8,20 @@
import logging
import typing
-from typing import Union
+from datetime import datetime, timedelta
import numpy as np
import spiceypy
from numpy import ndarray
+from imap_processing.ialirt.constants import STATIONS
from imap_processing.spice.geometry import SpiceBody, SpiceFrame, imap_state
-from imap_processing.spice.kernels import ensure_spice
from imap_processing.spice.time import et_to_utc, str_to_et
# Logger setup
logger = logging.getLogger(__name__)
-@typing.no_type_check
-@ensure_spice
def latitude_longitude_to_ecef(
longitude: float, latitude: float, altitude: float
) -> ndarray:
@@ -68,13 +66,13 @@ def latitude_longitude_to_ecef(
@typing.no_type_check
-@ensure_spice
def calculate_azimuth_and_elevation(
longitude: float,
latitude: float,
altitude: float,
- observation_time: Union[float, np.ndarray],
+ observation_time: float | np.ndarray,
target: str = SpiceBody.IMAP.name,
+ obsref: str = "ITRF93",
) -> tuple:
"""
Calculate azimuth and elevation.
@@ -94,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
-------
@@ -123,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]))
@@ -137,8 +138,8 @@ def calculate_doppler(
longitude: float,
latitude: float,
altitude: float,
- observation_time: Union[float, np.ndarray],
-) -> Union[float, ndarray[float]]:
+ observation_time: float | np.ndarray,
+) -> float | ndarray[float]:
"""
Calculate the doppler velocity.
@@ -194,7 +195,7 @@ def build_output(
latitude: float,
altitude: float,
time_endpoints: tuple[str, str],
- time_step: float,
+ time_step: float = 60,
) -> dict[str, np.ndarray]:
"""
Build the output dictionary containing time, azimuth, elevation, and doppler.
@@ -210,7 +211,7 @@ def build_output(
time_endpoints : tuple[str, str]
Start and stop times in UTC.
time_step : float
- Seconds between data points.
+ Seconds between data points. Default is 60.
Returns
-------
@@ -226,14 +227,14 @@ 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")
- output_dict["azimuth"] = azimuth
- output_dict["elevation"] = elevation
- output_dict["doppler"] = calculate_doppler(
- longitude, latitude, altitude, time_range
+ output_dict["azimuth"] = np.round(azimuth, 6)
+ output_dict["elevation"] = np.round(elevation, 6)
+ output_dict["doppler"] = np.round(
+ calculate_doppler(longitude, latitude, altitude, time_range), 6
)
logger.info(
@@ -242,3 +243,62 @@ def build_output(
)
return output_dict
+
+
+def generate_text_files(station: str, day: str) -> list[str]:
+ """
+ Generate a pointing schedule text file and return it as a list of strings.
+
+ Parameters
+ ----------
+ station : str
+ Station name.
+ day : str
+ The day for which to generate a pointing schedule, in ISO format.
+ Ex: "2025-08-11".
+
+ Returns
+ -------
+ lines : list[str]
+ A list of strings that makeup the lines of a pointing schedule file.
+ """
+ station_properties = STATIONS[station]
+
+ day_as_datetime = datetime.fromisoformat(day)
+ time_endpoints = (
+ datetime.strftime(day_as_datetime, "%Y-%m-%d %H:%M:%S"),
+ datetime.strftime(day_as_datetime + timedelta(days=1), "%Y-%m-%d %H:%M:%S"),
+ )
+ output_dict = build_output(
+ station_properties[0],
+ station_properties[1],
+ station_properties[2],
+ time_endpoints,
+ )
+
+ lines = [
+ f"Station: {station}\n",
+ "Target: IMAP\n",
+ f"Creation date (UTC): {datetime.utcnow()}\n",
+ f"Start time: {time_endpoints[0]}\n",
+ f"End time: {time_endpoints[1]}\n",
+ "Cadence (sec): 60\n\n",
+ "Date/Time"
+ + "Azimuth".rjust(29)
+ + "Elevation".rjust(17)
+ + "Doppler".rjust(15)
+ + "\n",
+ "(UTC)" + "(deg.)".rjust(33) + "(deg.)".rjust(16) + "(km/s)".rjust(16) + "\n",
+ ]
+
+ length = len(output_dict["time"])
+ for i in range(length):
+ lines.append(
+ f"{output_dict['time'][i]}"
+ + f"{output_dict['azimuth'][i]}".rjust(16)
+ + f"{output_dict['elevation'][i]}".rjust(16)
+ + f"{output_dict['doppler'][i]}".rjust(15)
+ + "\n"
+ )
+
+ return lines
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 bb94877ce0..6ffe119a84 100644
--- a/imap_processing/idex/idex_l0.py
+++ b/imap_processing/idex/idex_l0.py
@@ -2,18 +2,18 @@
import logging
from pathlib import Path
-from typing import Any, Union
+from typing import Any
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__)
def decom_packets(
- packet_file: Union[str, Path],
+ packet_file: str | Path,
) -> tuple[list[Any], dict[int, Dataset], dict[int, Dataset]]:
"""
Decom IDEX data packets using IDEX packet definition.
@@ -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 9f871e05b0..2e68afc0be 100644
--- a/imap_processing/idex/idex_l1a.py
+++ b/imap_processing/idex/idex_l1a.py
@@ -14,10 +14,10 @@
l1a_data.write_l1a_cdf()
"""
+import json
import logging
from enum import IntEnum
from pathlib import Path
-from typing import Union
import numpy as np
import numpy.typing as npt
@@ -25,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
@@ -61,7 +63,7 @@ class PacketParser:
The path and filename to the L0 file to read.
"""
- def __init__(self, packet_file: Union[str, Path]) -> None:
+ def __init__(self, packet_file: str | Path) -> None:
"""
Read a L0 pkts file and perform all of the decom work.
@@ -87,35 +89,142 @@ def __init__(self, packet_file: Union[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.
@@ -249,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: Union[float, np.ndarray], shfine_time: Union[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
-------
@@ -275,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:
@@ -289,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
@@ -341,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.
@@ -353,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
@@ -372,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(
@@ -421,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.
@@ -431,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
@@ -452,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
@@ -479,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]:
@@ -557,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
@@ -584,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.
"""
@@ -626,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 ffa0112ba3..2b767dd675 100644
--- a/imap_processing/idex/idex_l1b.py
+++ b/imap_processing/idex/idex_l1b.py
@@ -15,15 +15,18 @@
"""
import logging
-from enum import Enum
-from typing import Union
+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,
)
@@ -43,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.
@@ -81,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
----------
@@ -112,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,
@@ -226,7 +363,8 @@ def convert_waveforms(
def get_trigger_mode_and_level(
l1a_dataset: xr.Dataset,
-) -> Union[dict[str, xr.DataArray], dict]:
+ idex_attrs: ImapCdfAttributes,
+) -> dict[str, xr.DataArray] | dict:
"""
Determine the trigger mode and threshold level for each event.
@@ -234,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
-------
@@ -244,12 +384,12 @@ 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
- ) -> Union[tuple[str, Union[int, float]], tuple[None, None]]:
+ ) -> tuple[str, int | float] | tuple[None, None]:
"""
Compute the trigger mode label and threshold level.
@@ -303,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 1abad572f6..3c564a343a 100644
--- a/imap_processing/idex/idex_l2a.py
+++ b/imap_processing/idex/idex_l2a.py
@@ -24,7 +24,7 @@
import xarray as xr
from numpy.typing import NDArray
from scipy.integrate import quad
-from scipy.optimize import curve_fit
+from scipy.optimize import curve_fit, root_scalar
from scipy.signal import butter, detrend, filtfilt, find_peaks
from scipy.stats import exponnorm
@@ -52,7 +52,33 @@ class BaselineNoiseTime(IntEnum):
STOP = -5
-def idex_l2a(l1b_dataset: xr.Dataset) -> xr.Dataset:
+def load_calibration_files(ancillary_files: dict) -> tuple[NDArray, NDArray]:
+ """
+ Load calibration files for IDEX L2A processing.
+
+ Parameters
+ ----------
+ ancillary_files : dict
+ Dictionary containing paths to calibration files.
+
+ Returns
+ -------
+ numpy.ndarray
+ Calibration parameters for the rise time function.
+ numpy.ndarray
+ Calibration parameters for the charge yield function.
+ """
+ # Load calibration coefficients from ancillary files
+ t_rise_params = pd.read_csv(
+ ancillary_files["l2a-calibration-curve-t-rise"], skiprows=1, header=None
+ ).values.flatten()[:8]
+ yield_params = pd.read_csv(
+ ancillary_files["l2a-calibration-curve-yield-params"], skiprows=1, header=None
+ ).values.flatten()[:8]
+ return t_rise_params, yield_params
+
+
+def idex_l2a(l1b_dataset: xr.Dataset, ancillary_files: dict) -> xr.Dataset:
"""
Will process IDEX l1b data to create l2a data products.
@@ -68,6 +94,9 @@ def idex_l2a(l1b_dataset: xr.Dataset) -> xr.Dataset:
----------
l1b_dataset : xarray.Dataset
IDEX L1a dataset to process.
+ ancillary_files : dict
+ Ancillary files containing calibration coefficients needed to estimate
+ velocity and mass of the dust particles.
Returns
-------
@@ -79,6 +108,7 @@ def idex_l2a(l1b_dataset: xr.Dataset) -> xr.Dataset:
logger.info(
f"Running IDEX L2A processing on dataset: {l1b_dataset.attrs['Logical_source']}"
)
+ t_rise_params, yield_params = load_calibration_files(ancillary_files)
tof_high = l1b_dataset["TOF_High"]
hs_time = l1b_dataset["time_high_sample_rate"]
@@ -88,7 +118,7 @@ def idex_l2a(l1b_dataset: xr.Dataset) -> 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(
@@ -175,12 +205,26 @@ def idex_l2a(l1b_dataset: xr.Dataset) -> 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(
+ calculate_velocity_and_mass,
+ fit_results[1], # signal amplitude
+ fit_results[0].data[:, 3], # fit params
+ output_core_dims=[[], []],
+ vectorize=True,
+ output_dtypes=[np.float64, np.float64],
+ keep_attrs=True,
+ kwargs={"t_rise_params": t_rise_params, "yield_params": yield_params},
)
+
waveform_name = waveform.lower()
output_vars = {
f"{waveform_name}_fit_parameters": fit_results[0],
f"{waveform_name}_impact_charge": fit_results[1],
- f"{waveform_name}_dust_mass_estimate": fit_results[1],
+ f"{waveform_name}_velocity_estimate": velocity_mass_results[0],
+ f"{waveform_name}_dust_mass_estimate": velocity_mass_results[1],
# Same as impact_charge for now
f"{waveform_name}_chi_squared": fit_results[2],
f"{waveform_name}_reduced_chi_squared": fit_results[3],
@@ -256,11 +300,183 @@ def idex_l2a(l1b_dataset: xr.Dataset) -> 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
+def calculate_velocity_and_mass(
+ sig_amp: float, t_rise: float, t_rise_params: np.ndarray, yield_params: np.ndarray
+) -> tuple[float, float]:
+ """
+ Calculate velocity and mass estimates.
+
+ The fitted target signals are used to generate IDEXβs specific charge yield as a
+ function of the impact speed. The calibration curve is fitted with a
+ segmented power law distribution. The charge yield curve enables the mass of
+ the dust particle to be estimated from the total charge it generates on the target.
+
+ Parameters
+ ----------
+ sig_amp : float
+ Signal amplitude (pC).
+ t_rise : float
+ T_rise fit parameter from the target fit (us).
+ t_rise_params : np.ndarray
+ Calibration parameters for rise time (us).
+ yield_params : np.ndarray
+ Calibration parameters for yield.
+
+ Returns
+ -------
+ v_est : float
+ Estimated velocity.
+ mass_est : float
+ Estimated mass.
+ """
+ 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 log_v: (
+ log_smooth_powerlaw(log_v, log_a_t, t_rise_params[1:])
+ - target_log_t_rise
+ ),
+ bracket=[-1, 2],
+ method="brentq",
+ )
+ return 10**root.root
+ except Exception:
+ logger.error(
+ "Unable to calculate velocity estimate from rise time %.6g. "
+ "The rise-time calibration inversion failed. Returning nan.",
+ t_rise,
+ )
+ return np.nan
+
+
+def log_smooth_powerlaw(log_v: float, log_a: float, params: np.ndarray) -> float:
+ """
+ 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
+ The log10 input to the calibration curve.
+ This is log10(velocity [km/s]) for both the rise-time and yield cases.
+ log_a : float
+ Log10 of the calibration scale factor A.
+ params : np.ndarray
+ Calibration parameters for the power law
+ [a1, a2, a3, vb, vc, k, m].
+
+ Returns
+ -------
+ float
+ 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
+ v = 10**log_v
+ base = log_a + a1 * log_v
+ transition1 = (1 + (v / vb) ** k) ** ((a2 - a1) / k)
+ transition2 = (1 + (v / vc) ** k) ** ((a3 - a2) / k)
+ return base + np.log10(transition1 * transition2)
+
+
def time_to_mass(
tof_high: np.ndarray, high_sampling_time: np.ndarray, masses: np.ndarray
) -> tuple[NDArray, NDArray, NDArray]:
@@ -399,7 +615,7 @@ def calculate_kappa(mass_scales: np.ndarray, peaks_2d: list) -> NDArray:
kappas = np.asarray(
[
np.mean(mass_scale[peaks] - np.round(mass_scale[peaks]))
- for mass_scale, peaks in zip(mass_scales, peaks_2d)
+ for mass_scale, peaks in zip(mass_scales, peaks_2d, strict=False)
]
)
return kappas
@@ -622,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.
@@ -630,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
-------
@@ -655,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"):
@@ -691,6 +938,7 @@ def estimate_dust_mass(
time,
signal,
p0=p0,
+ bounds=bounds,
maxfev=100_000, # , epsfcn=1e-10
)
except RuntimeError as e:
@@ -709,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
@@ -730,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 79c8993038..d16aff0660 100644
--- a/imap_processing/idex/idex_l2b.py
+++ b/imap_processing/idex/idex_l2b.py
@@ -12,13 +12,15 @@
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_data = idex_l2b(l2a_data, [evt_data])
- write_cdf(l2b_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])
"""
import collections
@@ -28,13 +30,15 @@
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
from imap_processing.idex.idex_constants import (
FG_TO_KG,
+ 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
@@ -80,35 +84,46 @@
def idex_l2b(
- l2a_datasets: list[xr.Dataset], evt_datasets: list[xr.Dataset]
-) -> xr.Dataset:
+ l2a_datasets: list[xr.Dataset], msg_data_l1b: list[xr.Dataset]
+) -> list[xr.Dataset]:
"""
- Will process IDEX l2a data to create l2b data products.
+ Will process IDEX l2a data to create l2b and l2c data products.
+
+ IDEX L2B processing creates L2b and L2c at the same time because L2c needs no
+ additional dependencies and is a natural extension of L2b processing.
Parameters
----------
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
-------
- l2b_dataset : xarray.Dataset
- The``xarray`` dataset containing the science data and supporting metadata.
+ list[xarray.Dataset]
+ The``xarray`` datasets containing the l2b and l2c science data and supporting
+ metadata.
"""
logger.info(
- f"Running IDEX L2B processing on datasets: "
- f"{[ds.attrs['Logical_source'] for ds in l2a_datasets]}"
+ "Running IDEX L2B and L2C processing on L2a datasets. NOTE: L2C datasets are "
+ "processed at the same time as L2B datasets because L2C needs no additional "
+ "dependencies."
)
-
# create the attribute manager for this data level
- idex_attrs = get_idex_attrs("l2b")
- evt_dataset = xr.concat(evt_datasets, dim="epoch")
-
+ idex_l2b_attrs = get_idex_attrs("l2b")
+ idex_l2c_attrs = get_idex_attrs("l2c")
+ 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,
@@ -116,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,
@@ -133,125 +154,154 @@ def idex_l2b(
daily_on_percentage,
)
# Create l2b Dataset
- charge_bins = np.arange(len(CHARGE_BIN_EDGES) - 1)
- mass_bins = np.arange(len(CHARGE_BIN_EDGES) - 1)
- spin_phase_bins = np.arange(len(SPIN_PHASE_BIN_EDGES) - 1)
+ 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",
data=daily_epoch,
dims="epoch",
- attrs=idex_attrs.get_variable_attributes("epoch", check_schema=False),
+ attrs=idex_l2b_attrs.get_variable_attributes("epoch", check_schema=False),
)
- data_vars = {
+ 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,
dims="epoch",
- attrs=idex_attrs.get_variable_attributes("impact_day_of_year"),
- ),
- "rate_calculation_quality_flags": xr.DataArray(
- name="rate_calculation_quality_flags",
- data=rate_quality_flags,
- dims="epoch",
- attrs=idex_attrs.get_variable_attributes("rate_calculation_quality_flags"),
+ attrs=idex_l2b_attrs.get_variable_attributes("impact_day_of_year"),
),
"charge_labels": xr.DataArray(
name="impact_charge_labels",
- data=charge_bins.astype(str),
+ data=charge_bin_means.astype(str),
dims="impact_charge",
- attrs=idex_attrs.get_variable_attributes(
+ attrs=idex_l2b_attrs.get_variable_attributes(
"charge_labels", check_schema=False
),
),
- "spin_phase_labels": xr.DataArray(
- name="spin_phase_labels",
- data=spin_phase_bins.astype(str),
- dims="spin_phase",
- attrs=idex_attrs.get_variable_attributes(
- "spin_phase_labels", check_schema=False
- ),
- ),
"mass_labels": xr.DataArray(
name="mass_labels",
- data=mass_bins.astype(str),
+ data=mass_bin_means.astype(str),
dims="mass",
- attrs=idex_attrs.get_variable_attributes("mass_labels", check_schema=False),
- ),
- "rectangular_lon_pixel_label": xr.DataArray(
- name="rectangular_lon_pixel_label",
- data=SKY_GRID.az_bin_midpoints.astype(str),
- dims="rectangular_lon_pixel",
- attrs=idex_attrs.get_variable_attributes(
- "rectangular_lon_pixel_label", check_schema=False
- ),
- ),
- "rectangular_lat_pixel_label": xr.DataArray(
- name="rectangular_lat_pixel_label",
- data=SKY_GRID.el_bin_midpoints.astype(str),
- dims="rectangular_lat_pixel",
- attrs=idex_attrs.get_variable_attributes(
- "rectangular_lat_pixel_label", check_schema=False
+ attrs=idex_l2b_attrs.get_variable_attributes(
+ "mass_labels", check_schema=False
),
),
"impact_charge": xr.DataArray(
name="impact_charge",
- data=charge_bins,
+ data=charge_bin_means,
dims="impact_charge",
- attrs=idex_attrs.get_variable_attributes(
+ attrs=idex_l2b_attrs.get_variable_attributes(
"impact_charge", check_schema=False
),
),
"mass": xr.DataArray(
name="mass",
- data=mass_bins,
+ data=mass_bin_means,
dims="mass",
- attrs=idex_attrs.get_variable_attributes("mass", check_schema=False),
+ attrs=idex_l2b_attrs.get_variable_attributes("mass", check_schema=False),
),
+ }
+ l2b_vars = common_vars | {
"spin_phase": xr.DataArray(
name="spin_phase",
- data=spin_phase_bins,
+ data=spin_phase_means,
dims="spin_phase",
- attrs=idex_attrs.get_variable_attributes("spin_phase", check_schema=False),
+ attrs=idex_l2b_attrs.get_variable_attributes(
+ "spin_phase", check_schema=False
+ ),
),
- "rectangular_lon_pixel": xr.DataArray(
- name="rectangular_lon_pixel",
- data=SKY_GRID.az_bin_midpoints,
- dims="rectangular_lon_pixel",
- attrs=idex_attrs.get_variable_attributes(
- "rectangular_lon_pixel", check_schema=False
+ "spin_phase_labels": xr.DataArray(
+ name="spin_phase_labels",
+ data=spin_phase_means.astype(str),
+ dims="spin_phase",
+ attrs=idex_l2b_attrs.get_variable_attributes(
+ "spin_phase_labels", check_schema=False
),
),
- "rectangular_lat_pixel": xr.DataArray(
- name="rectangular_lat_pixel",
- data=SKY_GRID.el_bin_midpoints,
- dims="rectangular_lat_pixel",
- attrs=idex_attrs.get_variable_attributes(
- "rectangular_lat_pixel", check_schema=False
+ "rate_calculation_quality_flags": xr.DataArray(
+ name="rate_calculation_quality_flags",
+ data=rate_quality_flags,
+ dims="epoch",
+ attrs=idex_l2b_attrs.get_variable_attributes(
+ "rate_calculation_quality_flags"
),
),
"counts_by_charge": xr.DataArray(
name="counts_by_charge",
data=counts_by_charge.astype(np.int64),
dims=("epoch", "impact_charge", "spin_phase"),
- attrs=idex_attrs.get_variable_attributes("counts_by_charge"),
+ attrs=idex_l2b_attrs.get_variable_attributes("counts_by_charge"),
),
"counts_by_mass": xr.DataArray(
name="counts_by_mass",
data=counts_by_mass.astype(np.int64),
dims=("epoch", "mass", "spin_phase"),
- attrs=idex_attrs.get_variable_attributes("counts_by_mass"),
+ attrs=idex_l2b_attrs.get_variable_attributes("counts_by_mass"),
),
"rate_by_charge": xr.DataArray(
name="rate_by_charge",
data=rate_by_charge,
dims=("epoch", "impact_charge", "spin_phase"),
- attrs=idex_attrs.get_variable_attributes("rate_by_charge"),
+ attrs=idex_l2b_attrs.get_variable_attributes("rate_by_charge"),
),
"rate_by_mass": xr.DataArray(
name="rate_by_mass",
data=rate_by_mass,
dims=("epoch", "mass", "spin_phase"),
- attrs=idex_attrs.get_variable_attributes("rate_by_mass"),
+ attrs=idex_l2b_attrs.get_variable_attributes("rate_by_mass"),
+ ),
+ }
+ l2c_vars = common_vars | {
+ "rectangular_lon_pixel_label": xr.DataArray(
+ name="rectangular_lon_pixel_label",
+ data=SKY_GRID.az_bin_midpoints.astype(str),
+ dims="rectangular_lon_pixel",
+ attrs=idex_l2c_attrs.get_variable_attributes(
+ "rectangular_lon_pixel_label", check_schema=False
+ ),
+ ),
+ "rectangular_lat_pixel_label": xr.DataArray(
+ name="rectangular_lat_pixel_label",
+ data=SKY_GRID.el_bin_midpoints.astype(str),
+ dims="rectangular_lat_pixel",
+ attrs=idex_l2c_attrs.get_variable_attributes(
+ "rectangular_lat_pixel_label", check_schema=False
+ ),
+ ),
+ "rectangular_lon_pixel": xr.DataArray(
+ name="rectangular_lon_pixel",
+ data=SKY_GRID.az_bin_midpoints,
+ dims="rectangular_lon_pixel",
+ attrs=idex_l2c_attrs.get_variable_attributes(
+ "rectangular_lon_pixel", check_schema=False
+ ),
+ ),
+ "rectangular_lat_pixel": xr.DataArray(
+ name="rectangular_lat_pixel",
+ data=SKY_GRID.el_bin_midpoints,
+ dims="rectangular_lat_pixel",
+ attrs=idex_l2c_attrs.get_variable_attributes(
+ "rectangular_lat_pixel", check_schema=False
+ ),
),
"counts_by_charge_map": xr.DataArray(
name="counts_by_charge_map",
@@ -262,7 +312,7 @@ def idex_l2b(
"rectangular_lon_pixel",
"rectangular_lat_pixel",
),
- attrs=idex_attrs.get_variable_attributes("counts_by_charge_map"),
+ attrs=idex_l2c_attrs.get_variable_attributes("counts_by_charge_map"),
),
"counts_by_mass_map": xr.DataArray(
name="counts_by_mass_map",
@@ -273,7 +323,7 @@ def idex_l2b(
"rectangular_lon_pixel",
"rectangular_lat_pixel",
),
- attrs=idex_attrs.get_variable_attributes("counts_by_mass_map"),
+ attrs=idex_l2c_attrs.get_variable_attributes("counts_by_mass_map"),
),
"rate_by_charge_map": xr.DataArray(
name="rate_by_charge_map",
@@ -284,7 +334,7 @@ def idex_l2b(
"rectangular_lon_pixel",
"rectangular_lat_pixel",
),
- attrs=idex_attrs.get_variable_attributes("rate_by_charge_map"),
+ attrs=idex_l2c_attrs.get_variable_attributes("rate_by_charge_map"),
),
"rate_by_mass_map": xr.DataArray(
name="rate_by_mass_map",
@@ -295,18 +345,61 @@ def idex_l2b(
"rectangular_lon_pixel",
"rectangular_lat_pixel",
),
- attrs=idex_attrs.get_variable_attributes("rate_by_mass_map"),
+ attrs=idex_l2c_attrs.get_variable_attributes("rate_by_mass_map"),
),
}
l2b_dataset = xr.Dataset(
coords={"epoch": epoch},
- data_vars=data_vars,
- attrs=idex_attrs.get_global_attributes("imap_idex_l2b_sci"),
+ data_vars=l2b_vars,
+ attrs=idex_l2b_attrs.get_global_attributes("imap_idex_l2b_sci"),
+ )
+ l2c_dataset = xr.Dataset(
+ coords={"epoch": epoch},
+ data_vars=l2c_vars,
+ )
+ # Add map attributes
+ map_attrs = {
+ "sky_tiling_type": SkyTilingType.RECTANGULAR.value,
+ "Spacing_degrees": str(IDEX_SPACING_DEG),
+ "Spice_reference_frame": IDEX_EVENT_REFERENCE_FRAME.name,
+ } | idex_l2c_attrs.get_global_attributes("imap_idex_l2c_sci-rectangular")
+
+ l2c_dataset.attrs.update(map_attrs)
+
+ # 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
)
- logger.info("IDEX L2B science data processing completed.")
+ # 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
+ )
- return l2b_dataset
+ logger.info("IDEX L2B and L2C science data processing completed.")
+ return [l2b_dataset, l2c_dataset]
def compute_counts_by_charge_and_mass(
@@ -329,38 +422,12 @@ def compute_counts_by_charge_and_mass(
dataset, Two 4D arrays containing counts by charge or mass, and by lon and lat
for each dataset, and a 1D array of daily epoch values.
"""
- # Initialize arrays to hold counts.
- # There should be 4 spin phase bins, 10 charge bins, and 10 mass bins.
- # The first bin for charge and mass is for values below the first bin edge.
- counts_by_charge = np.zeros(
- (
- len(epoch_doy_unique),
- len(CHARGE_BIN_EDGES) - 1,
- len(SPIN_PHASE_BIN_EDGES) - 1,
- ),
- )
- counts_by_mass = np.zeros(
- (len(epoch_doy_unique), len(MASS_BIN_EDGES) - 1, len(SPIN_PHASE_BIN_EDGES) - 1),
- )
- # Initialize arrays to hold count maps. Each map is a 3 or 4D array with shape
- # (epoch, 10 [charge or mass], 60 [longitude bins], 30 [latitude bins]).
- counts_by_charge_map = np.zeros(
- (
- len(epoch_doy_unique),
- len(CHARGE_BIN_EDGES) - 1,
- len(LON_BINS_EDGES) - 1,
- len(LAT_BINS_EDGES) - 1,
- ),
- )
- counts_by_mass_map = np.zeros(
- (
- len(epoch_doy_unique),
- len(MASS_BIN_EDGES) - 1,
- len(LON_BINS_EDGES) - 1,
- len(LAT_BINS_EDGES) - 1,
- ),
- )
- daily_epoch = np.zeros(len(epoch_doy_unique), dtype=np.float64)
+ # Initialize lists to hold counts.
+ counts_by_charge = []
+ counts_by_mass = []
+ counts_by_charge_map = []
+ counts_by_mass_map = []
+ 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
@@ -379,43 +446,44 @@ def compute_counts_by_charge_and_mass(
latitude = l2a_dataset["latitude"].data[current_day_indices]
# Convert units
mass_vals = FG_TO_KG * np.atleast_1d(mass_vals)
- # Bin masses
- binned_mass = np.asarray(np.digitize(mass_vals, bins=MASS_BIN_EDGES))
- # Bin charges
- binned_charge = np.asarray(np.digitize(charge_vals, bins=CHARGE_BIN_EDGES))
# Bin spin phases
binned_spin_phase = bin_spin_phases(spin_phase_angles)
- # Bin longitude and latitude into the rectangular grid.
- binned_longitude = np.asarray(np.digitize(longitude, bins=LON_BINS_EDGES))
+ # Clip arrays to ensure that the values are within the valid range of bins.
# Latitude should be binned with the right edge included. 90 is a valid latitude
- binned_latitude = np.asarray(np.digitize(latitude, bins=LAT_BINS_EDGES))
- # Clip latitude value above the right edge to be in the last bin
- binned_latitude = np.clip(binned_latitude, 1, len(LAT_BINS_EDGES) - 1)
- # If the values in the array are beyond the bounds of bins, 0 or len(bins) it is
- # returned as such. In this case, the desired result is to place the values
- # beyond the first or last bin into the first or last bin, respectively.
- binned_charge = np.clip(binned_charge, 1, len(CHARGE_BIN_EDGES) - 1)
- binned_mass = np.clip(binned_mass, 1, len(MASS_BIN_EDGES) - 1)
-
- # Count dust events for each spin phase, mass bin, charge bin, and bin into
- # a rectangular grid
- for mass_bin, charge_bin, spin_phase_bin, lon_bin, lat_bin in zip(
- binned_mass,
- binned_charge,
- binned_spin_phase,
- binned_longitude,
- binned_latitude,
- ):
- counts_by_mass[i, mass_bin - 1, spin_phase_bin] += 1
- counts_by_charge[i, charge_bin - 1, spin_phase_bin] += 1
- counts_by_mass_map[i, mass_bin - 1, lon_bin - 1, lat_bin - 1] += 1
- counts_by_charge_map[i, charge_bin - 1, lon_bin - 1, lat_bin - 1] += 1
+ latitude = np.clip(latitude, -90, 90)
+ mass_vals = np.clip(mass_vals, MASS_BIN_EDGES[0], MASS_BIN_EDGES[-1])
+ charge_vals = np.clip(charge_vals, CHARGE_BIN_EDGES[0], CHARGE_BIN_EDGES[-1])
+
+ counts_by_mass.append(
+ np.histogramdd(
+ np.column_stack([mass_vals, binned_spin_phase]),
+ bins=[MASS_BIN_EDGES, np.arange(5)],
+ )[0]
+ )
+ counts_by_charge.append(
+ np.histogramdd(
+ np.column_stack([charge_vals, binned_spin_phase]),
+ bins=[CHARGE_BIN_EDGES, np.arange(5)],
+ )[0]
+ )
+ counts_by_mass_map.append(
+ np.histogramdd(
+ np.column_stack([mass_vals, longitude, latitude]),
+ bins=[MASS_BIN_EDGES, LON_BINS_EDGES, LAT_BINS_EDGES],
+ )[0]
+ )
+ counts_by_charge_map.append(
+ np.histogramdd(
+ np.column_stack([charge_vals, longitude, latitude]),
+ bins=[CHARGE_BIN_EDGES, LON_BINS_EDGES, LAT_BINS_EDGES],
+ )[0]
+ )
return (
- counts_by_charge,
- counts_by_mass,
- counts_by_charge_map,
- counts_by_mass_map,
+ np.stack(counts_by_charge),
+ np.stack(counts_by_mass),
+ np.stack(counts_by_charge_map),
+ np.stack(counts_by_mass_map),
daily_epoch,
)
@@ -558,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):
- # 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
-------
@@ -635,23 +645,27 @@ 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(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."
+ )
+ return {}
# Track total and 'on' durations per day
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_l2c.py b/imap_processing/idex/idex_l2c.py
deleted file mode 100644
index ee4302f1d0..0000000000
--- a/imap_processing/idex/idex_l2c.py
+++ /dev/null
@@ -1,84 +0,0 @@
-"""
-Perform IDEX L2c Processing.
-
-Examples
---------
-.. code-block:: python
- from imap_processing.idex.idex_l1a import PacketParser
- 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.cdf.utils import write_cdf
-
- l0_file = "imap_processing/tests/idex/imap_idex_l0_sci_20231214_v001.pkts"
- l1a_data = PacketParser(l0_file)
- l1b_data = idex_l1b(l1a_data)
- l2a_data = idex_l2a(l1b_data)
- l2b_data = idex_l2b(l2a_data)
- write_cdf(l2b_data)
-"""
-
-import logging
-
-import xarray as xr
-
-from imap_processing.ena_maps.ena_maps import SkyTilingType
-from imap_processing.idex.idex_constants import (
- IDEX_EVENT_REFERENCE_FRAME,
- IDEX_SPACING_DEG,
-)
-from imap_processing.idex.idex_utils import get_idex_attrs, setup_dataset
-
-logger = logging.getLogger(__name__)
-
-
-def idex_l2c(l2b_datasets: list[xr.Dataset]) -> xr.Dataset:
- """
- Will process IDEX l2b data to create l2c data products.
-
- Parameters
- ----------
- l2b_datasets : list[xarray.Dataset]
- IDEX L2b datasets.
-
- Returns
- -------
- l2b_dataset : xarray.Dataset
- The``xarray`` dataset containing the science data and supporting metadata.
- """
- logger.info("Running IDEX L2C processing")
- # create the attribute manager for this data level
- idex_attrs = get_idex_attrs("l2c")
- # Concat the list of l2b datasets into a single dataset
- # Only concat the variables that have "epoch" as a dimension
- l2b_dataset = xr.concat(
- l2b_datasets, "epoch", data_vars="minimal", coords="minimal"
- )
-
- arrays_to_copy = [
- "counts_by_charge_map",
- "counts_by_mass_map",
- "rate_by_charge_map",
- "rate_by_mass_map",
- "epoch",
- "impact_day_of_year",
- "impact_charge_bins",
- "mass_bins",
- "charge_labels",
- "mass_labels",
- "rectangular_lon_pixel_label",
- "rectangular_lat_pixel_label",
- ]
-
- l2c_dataset = setup_dataset(l2b_dataset, arrays_to_copy, idex_attrs)
-
- # Add map attributes
- map_attrs = {
- "sky_tiling_type": SkyTilingType.RECTANGULAR.value,
- "Spacing_degrees": str(IDEX_SPACING_DEG),
- "Spice_reference_frame": IDEX_EVENT_REFERENCE_FRAME.name,
- } | idex_attrs.get_global_attributes("imap_idex_l2c_sci-rectangular")
-
- l2c_dataset.attrs.update(map_attrs)
- logger.info("IDEX L2C science data processing completed.")
- return l2c_dataset
diff --git a/imap_processing/idex/idex_utils.py b/imap_processing/idex/idex_utils.py
index 440fc8cca3..2d33029690 100644
--- a/imap_processing/idex/idex_utils.py
+++ b/imap_processing/idex/idex_utils.py
@@ -1,7 +1,5 @@
"""Contains helper functions to support IDEX processing."""
-from typing import Optional
-
import xarray as xr
from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
@@ -31,7 +29,7 @@ def setup_dataset(
dataset: xr.Dataset,
match_strings: list,
idex_attrs: ImapCdfAttributes,
- data_vars: Optional[dict] = None,
+ data_vars: dict | None = None,
) -> xr.Dataset:
"""
Initialize a dataset and copy over any dataArrays.
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 e22f2807c7..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",
@@ -37,28 +36,28 @@
HIST_DATA_META = {
# field: bit_length, section_length, shape
- "start_a": HistPacking(12, 504, (6, 7)),
- "start_c": HistPacking(12, 504, (6, 7)),
- "stop_b0": HistPacking(12, 504, (6, 7)),
- "stop_b3": HistPacking(12, 504, (6, 7)),
- "tof0_count": HistPacking(8, 336, (6, 7)),
- "tof1_count": HistPacking(8, 336, (6, 7)),
- "tof2_count": HistPacking(8, 336, (6, 7)),
- "tof3_count": HistPacking(8, 336, (6, 7)),
- "tof0_tof1": HistPacking(8, 3360, (60, 7)),
- "tof0_tof2": HistPacking(8, 3360, (60, 7)),
- "tof1_tof2": HistPacking(8, 3360, (60, 7)),
- "silver": HistPacking(8, 3360, (60, 7)),
- "disc_tof0": HistPacking(8, 336, (6, 7)),
- "disc_tof1": HistPacking(8, 336, (6, 7)),
- "disc_tof2": HistPacking(8, 336, (6, 7)),
- "disc_tof3": HistPacking(8, 336, (6, 7)),
- "pos0": HistPacking(12, 504, (6, 7)),
- "pos1": HistPacking(12, 504, (6, 7)),
- "pos2": HistPacking(12, 504, (6, 7)),
- "pos3": HistPacking(12, 504, (6, 7)),
- "hydrogen": HistPacking(8, 3360, (60, 7)),
- "oxygen": HistPacking(8, 3360, (60, 7)),
+ "start_a": HistPacking(12, 504, (7, 6)),
+ "start_c": HistPacking(12, 504, (7, 6)),
+ "stop_b0": HistPacking(12, 504, (7, 6)),
+ "stop_b3": HistPacking(12, 504, (7, 6)),
+ "tof0_count": HistPacking(8, 336, (7, 6)),
+ "tof1_count": HistPacking(8, 336, (7, 6)),
+ "tof2_count": HistPacking(8, 336, (7, 6)),
+ "tof3_count": HistPacking(8, 336, (7, 6)),
+ "tof0_tof1": HistPacking(8, 3360, (7, 60)),
+ "tof0_tof2": HistPacking(8, 3360, (7, 60)),
+ "tof1_tof2": HistPacking(8, 3360, (7, 60)),
+ "silver": HistPacking(8, 3360, (7, 60)),
+ "disc_tof0": HistPacking(8, 336, (7, 6)),
+ "disc_tof1": HistPacking(8, 336, (7, 6)),
+ "disc_tof2": HistPacking(8, 336, (7, 6)),
+ "disc_tof3": HistPacking(8, 336, (7, 6)),
+ "pos0": HistPacking(12, 504, (7, 6)),
+ "pos1": HistPacking(12, 504, (7, 6)),
+ "pos2": HistPacking(12, 504, (7, 6)),
+ "pos3": HistPacking(12, 504, (7, 6)),
+ "hydrogen": HistPacking(8, 3360, (7, 60)),
+ "oxygen": HistPacking(8, 3360, (7, 60)),
}
@@ -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)
- 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]
+ # Process all direct events in this packet
+ for de_idx in range(de_count):
+ current_de_idx = pointing_de + de_idx
+
+ # 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
+ )
+ 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],
)
- dataset.attrs["bit_pos"] += bit_length
+ ]
- 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)
- ]
+ # 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"
)
@@ -441,7 +453,8 @@ def find_valid_groups(
"""
# Check if the sequence counters from the CCSDS header are sequential
grouped_seq_ctrs = [
- np.array(seq_ctrs[start : end + 1]) for start, end in zip(seg_starts, seg_ends)
+ np.array(seq_ctrs[start : end + 1])
+ for start, end in zip(seg_starts, seg_ends, strict=False)
]
valid_groups = [is_sequential(seq_ctrs) for seq_ctrs in grouped_seq_ctrs]
return valid_groups
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 2802fce354..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, Union
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) -> Union[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
@@ -587,7 +1049,7 @@ def convert_tofs_to_eu(
tof_conversions = [TOF0_CONV, TOF1_CONV, TOF2_CONV, TOF3_CONV]
# Loop through the TOF fields and convert them to engineering units
- for tof, conv in zip(tof_fields, tof_conversions):
+ for tof, conv in zip(tof_fields, tof_conversions, strict=False):
# Get the fill value for the L1A and L1B TOF
fillval_1a = attr_mgr_l1a.get_variable_attributes(tof)["FILLVAL"]
fillval_1b = attr_mgr_l1b.get_variable_attributes(tof)["FILLVAL"]
@@ -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 fa819ce88e..2eb43c99da 100644
--- a/imap_processing/lo/l1c/lo_l1c.py
+++ b/imap_processing/lo/l1c/lo_l1c.py
@@ -1,15 +1,50 @@
"""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.spice.time import met_to_ttj2000ns
+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_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
+N_OFF_ANGLE_BINS = 40
+# 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.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):
@@ -52,10 +87,84 @@ 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, 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]
+ )
+ )
+
+ 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",
+ attrs=attr_mgr.get_variable_attributes("pointing_start_met"),
+ )
+ pset["pointing_end_met"] = xr.DataArray(
+ np.array([pointing_end_met]),
+ dims="epoch",
+ attrs=attr_mgr.get_variable_attributes("pointing_end_met"),
+ )
+
+ # 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(
+ [start_spin_number],
+ dims="epoch",
+ attrs=attr_mgr.get_variable_attributes("start_spin_number"),
+ )
+ pset["end_spin_number"] = xr.DataArray(
+ [end_spin_number],
+ dims="epoch",
+ attrs=attr_mgr.get_variable_attributes("end_spin_number"),
+ )
- 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)
+ # Set the counts
pset["triples_counts"] = create_pset_counts(
l1b_goodtimes_only, FilterType.TRIPLES
)
@@ -64,104 +173,267 @@ 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 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)
- # TODO: Temp fix before adding attribute variables.
- # CDF won't open if DEPEND_0 is not deleted currently.
- del pset["epoch"].attrs["DEPEND_0"]
pset = pset.assign_coords(
{
- "energy": np.arange(1, 8),
- "longitude": np.arange(3600),
- "latitude": np.arange(40),
+ "esa_energy_step": ESA_ENERGY_STEPS,
+ "spin_angle": SPIN_ANGLE_BIN_CENTERS,
+ "off_angle": OFF_ANGLE_BIN_CENTERS,
}
)
+ # 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 = pd.read_csv(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):
- 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.
@@ -174,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".
@@ -183,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],
)
@@ -249,54 +491,397 @@ def create_pset_counts(
counts = xr.DataArray(
data=hist.astype(np.int16),
- dims=["epoch", "energy", "longitude", "latitude"],
+ dims=PSET_DIMS,
)
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).
"""
- # Create bin edges
- lon_edges = np.arange(3601)
- lat_edges = np.arange(41)
- energy_edges = np.arange(8)
+ # Calculate total pointing duration in seconds
+ total_pointing_duration = pointing_end_met - pointing_start_met
- data = np.column_stack(
- (l1b_de["esa_step"], l1b_de["pointing_bin_lon"], l1b_de["pointing_bin_lat"])
+ 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",
- bins=[energy_edges, lon_edges, lat_edges],
+ # 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}"
+ )
+
+ # 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"
+ )
- stat = result.statistic[np.newaxis, :, :, :]
+ # Add epoch dimension
+ exposure_4d = exposure_3d[np.newaxis, :, :, :]
exposure_time = xr.DataArray(
- data=stat.astype(np.float16),
- dims=["epoch", "energy", "longitude", "latitude"],
+ 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
@@ -328,8 +913,6 @@ def create_datasets(
# can be used direction
epoch_converted_time = [1]
- # Create a data array for the epoch time
- # TODO: might need to update the attrs to use new YAML file
epoch_time = xr.DataArray(
data=epoch_converted_time,
name="epoch",
@@ -338,38 +921,54 @@ def create_datasets(
)
if logical_source == "imap_lo_l1c_pset":
- esa_step = xr.DataArray(
- data=[1, 2, 3, 4, 5, 6, 7],
- name="esa_step",
- dims=["esa_step"],
- attrs=attr_mgr.get_variable_attributes("esa_step"),
+ esa_energy_step = xr.DataArray(
+ data=ESA_ENERGY_STEPS,
+ name="esa_energy_step",
+ dims=["esa_energy_step"],
+ attrs=attr_mgr.get_variable_attributes("esa_energy_step"),
)
- pointing_bins = xr.DataArray(
- data=np.arange(3600),
- name="pointing_bins",
- dims=["pointing_bins"],
- attrs=attr_mgr.get_variable_attributes("pointing_bins"),
- )
-
- esa_step_label = xr.DataArray(
- esa_step.values.astype(str),
+ esa_energy_step_label = xr.DataArray(
+ esa_energy_step.values.astype(str),
name="esa_step_label",
dims=["esa_step_label"],
attrs=attr_mgr.get_variable_attributes("esa_step_label"),
)
- pointing_bins_label = xr.DataArray(
- pointing_bins.values.astype(str),
- name="pointing_bins_label",
- dims=["pointing_bins_label"],
- attrs=attr_mgr.get_variable_attributes("pointing_bins_label"),
+
+ spin_angle = xr.DataArray(
+ data=SPIN_ANGLE_BIN_CENTERS,
+ name="spin_angle",
+ dims=["spin_angle"],
+ attrs=attr_mgr.get_variable_attributes("spin_angle"),
+ )
+ spin_angle_label = xr.DataArray(
+ spin_angle.values.astype(str),
+ name="spin_angle_label",
+ dims=["spin_angle_label"],
+ attrs=attr_mgr.get_variable_attributes("spin_angle_label"),
)
+
+ off_angle = xr.DataArray(
+ data=OFF_ANGLE_BIN_CENTERS,
+ name="off_angle",
+ dims=["off_angle"],
+ attrs=attr_mgr.get_variable_attributes("off_angle"),
+ )
+ off_angle_label = xr.DataArray(
+ off_angle.values.astype(str),
+ name="off_angle_label",
+ dims=["off_angle_label"],
+ attrs=attr_mgr.get_variable_attributes("off_angle_label"),
+ )
+
dataset = xr.Dataset(
coords={
"epoch": epoch_time,
- "pointing_bins": pointing_bins,
- "pointing_bins_label": pointing_bins_label,
- "esa_step": esa_step,
- "esa_step_label": esa_step_label,
+ "esa_energy_step": esa_energy_step,
+ "esa_energy_step_label": esa_energy_step_label,
+ "spin_angle": spin_angle,
+ "spin_angle_label": spin_angle_label,
+ "off_angle": off_angle,
+ "off_angle_label": off_angle_label,
},
attrs=attr_mgr.get_global_attributes(logical_source),
)
@@ -389,32 +988,204 @@ def create_datasets(
# Create a data array for the current field and add it to the dataset
# TODO: TEMPORARY. need to update to use l1b data once that's available.
- if field in ["pointing_start", "pointing_end", "mode", "pivot_angle"]:
+ if field in [
+ "pointing_start_met",
+ "pointing_end_met",
+ "esa_mode",
+ "pivot_angle",
+ ]:
dataset[field] = xr.DataArray(
data=[1],
dims=dims,
attrs=attr_mgr.get_variable_attributes(field),
)
# TODO: This is temporary.
- # The data type will be set in the data class when that's created
elif field == "exposure_time":
dataset[field] = xr.DataArray(
- data=np.ones((1, 7), dtype=np.float16),
+ data=np.ones((1, 7, 3600, 40), dtype=np.float16),
dims=dims,
attrs=attr_mgr.get_variable_attributes(field),
)
- elif "rate" in field:
+ elif "rates" in field:
dataset[field] = xr.DataArray(
- data=np.ones((1, 3600, 7), dtype=np.float16),
+ data=np.ones(PSET_SHAPE, dtype=np.float16),
dims=dims,
attrs=attr_mgr.get_variable_attributes(field),
)
else:
dataset[field] = xr.DataArray(
- data=np.ones((1, 3600, 7), dtype=np.int16),
+ data=np.ones(PSET_SHAPE, dtype=np.int16),
dims=dims,
attrs=attr_mgr.get_variable_attributes(field),
)
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 a15072edf3..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 RectangularSkyMap
-from imap_processing.spice import geometry
-from imap_processing.spice.geometry import SpiceFrame
+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) -> list[xr.Dataset]:
+
+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
-------
- created_file_paths : list[Path]
- Location of created CDF files.
+ pd.DataFrame
+ Concatenated efficiency factor data from all matching files.
+ Returns empty DataFrame if no efficiency files found.
"""
- # create the attribute manager for this data level
+ 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 descriptor for this map dataset.
+
+ Returns
+ -------
+ xr.Dataset
+ The finalized dataset with all attributes added.
+ """
+ # 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"))
+
+ # 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}")
+
+ return dataset
+
- # Create the rectangular sky map from the pointing set.
- lo_rect_map = project_pset_to_rect_map(
- psets, spacing_deg=6, spice_frame=geometry.SpiceFrame.ECLIPJ2000
+# =============================================================================
+# SKY MAP CREATION PIPELINE
+# =============================================================================
+
+
+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 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 populated sky map with projected data from all pointing sets.
+
+ Raises
+ ------
+ NotImplementedError
+ If HEALPix map output is requested (only rectangular maps supported).
+ """
+ # Initialize the output map
+ output_map = map_descriptor.to_empty_map()
+
+ 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,
)
- # Add the hydrogen rates to the rectangular map dataset.
- lo_rect_map.data_1d["h_rate"] = calculate_rates(
- lo_rect_map.data_1d["h_counts"], lo_rect_map.data_1d["exposure_time"]
+ 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 process_single_pset(
+ pset: xr.Dataset,
+ efficiency_data: pd.DataFrame,
+ species: str,
+ cg_correct: bool = False,
+) -> xr.Dataset:
+ """
+ Process a single pointing set for projection to the sky map.
+
+ Parameters
+ ----------
+ 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.Dataset
+ Processed pointing set ready for projection with efficiency corrections applied.
+ """
+ # 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.
+
+ # 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
)
- # Add the hydrogen flux to the rectangular map dataset.
- lo_rect_map.data_1d["h_flux"] = calculate_fluxes(lo_rect_map.data_1d["h_rate"])
- # Create the dataset from the rectangular map.
- lo_rect_map_ds = lo_rect_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
+ # Prepare energy_sc for exposure time weighted projection
+ pset_processed["energy_sc_exposure_factor"] = (
+ pset_processed["energy_sc"] * pset_processed["exposure_factor"]
)
- return [lo_rect_map_ds]
+ # Always calculate ram-mask to identify ram/anti-ram bins
+ pset_processed = calculate_ram_mask(pset_processed)
+ return pset_processed
-def project_pset_to_rect_map(
- psets: list[xr.Dataset], spacing_deg: int, spice_frame: SpiceFrame
-) -> RectangularSkyMap:
+
+def normalize_pset_coordinates(pset: xr.Dataset, species: str) -> xr.Dataset:
"""
- Project the pointing set to a rectangular sky map.
+ Normalize pointing set coordinates to match the output map.
- This function is used to create a rectangular sky map from the pointing set
- data in the L1C dataset.
+ Parameters
+ ----------
+ pset : xr.Dataset
+ Input pointing set dataset with potentially mismatched coordinates.
+ species : str
+ The species to process (e.g., "h", "o").
+
+ Returns
+ -------
+ xr.Dataset
+ Pointing set with normalized energy coordinates and dimension names.
+ """
+ # 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)
+
+ return pset_renamed
+
+
+def add_efficiency_factors_to_pset(
+ pset: xr.Dataset, efficiency_data: pd.DataFrame
+) -> xr.Dataset:
+ """
+ Add efficiency factors to the pointing set based on observation date.
Parameters
----------
- psets : list[xr.Dataset]
- List of pointing sets in xarray Dataset format.
- spacing_deg : int
- The spacing in degrees for the rectangular sky map.
- spice_frame : SpiceFrame
- The SPICE frame to use for the rectangular sky map projection.
+ 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
+ Pointing set with efficiency factors added as new data variable.
+
+ Raises
+ ------
+ ValueError
+ If no efficiency factor found for the pointing set observation date.
+ """
+ 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
+
+ # 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)
+
+ 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
-------
- RectangularSkyMap
- The rectangular sky map created from the pointing set data.
+ None
+ Function modifies output_map in place.
"""
- lo_rect_map = ena_maps.RectangularSkyMap(
- spacing_deg=spacing_deg,
- spice_frame=spice_frame,
+ # 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,
)
- for pset in psets:
- lo_pset = ena_maps.LoPointingSet(pset)
- lo_rect_map.project_pset_values_to_map(
- pointing_set=lo_pset,
- value_keys=["h_counts", "exposure_time"],
- index_match_method=ena_maps.IndexMatchMethod.PUSH,
+ 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}'"
)
- return lo_rect_map
+ 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"
-def calculate_rates(counts: xr.DataArray, exposure_time: xr.DataArray) -> xr.DataArray:
+ return lo_ancillary.read_ancillary_file(gf_file)
+
+
+def reduce_geometric_factor_dataset(species: str, esa_mode: int) -> xr.Dataset:
"""
- Calculate the hydrogen rates from the counts and exposure time.
+ 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
----------
- counts : xr.DataArray
- The counts of hydrogen or oxygen ENAs.
- exposure_time : xr.DataArray
- The exposure time for the counts.
+ species : str
+ The species to load geometric factors for ("h" or "o").
+ esa_mode : int
+ ESA mode (0 for HiRes, 1 for HiThr).
Returns
-------
- xr.DataArray
- The calculated hydrogen rates.
+ xarray.Dataset
+ Geometric factor data indexed by Observed_E-Step (1-7), containing all
+ columns from the geometric factor CSV file.
"""
- # Calculate the rates based on the h_counts and exposure_time
- rate = counts / exposure_time
- return rate
+ # 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 calculate_fluxes(rates: xr.DataArray) -> xr.DataArray:
+def initialize_geometric_factor_variables(
+ dataset: xr.Dataset,
+) -> xr.Dataset:
"""
- Calculate the flux from the hydrogen rate.
+ Initialize geometric factor variables for the specified species.
Parameters
----------
- rates : xr.Dataset
- The hydrogen or oxygen rates.
+ dataset : xr.Dataset
+ Input dataset to add geometric factor variables to.
Returns
-------
- xr.DataArray
- The calculated flux.
+ xr.Dataset
+ Dataset with initialized geometric factor variables for the specified species.
"""
- # 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)
+ 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"],
+ )
- flux = rates / (geometric_factor * energies * efficiency_factor)
- return flux
+ return dataset
-def add_attributes(
- lo_map: xr.Dataset, attr_mgr: ImapCdfAttributes, logical_source: str
+def populate_geometric_factors(
+ dataset: xr.Dataset,
+ species: str,
) -> xr.Dataset:
"""
- Add attributes to the map dataset.
+ Populate geometric factor values for each energy step.
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.
+ 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
- The dataset with added attributes.
+ Dataset with populated geometric factor values for the specified species.
"""
- # Add the global attributes to the dataset.
- lo_map.attrs.update(attr_mgr.get_global_attributes(logical_source))
+ # 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
- # 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",
+ # 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",
}
+ 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
+ )
- # 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)
- )
+ # 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
- labels = {
- "energy": np.arange(1, 8).astype(str),
- "longitude": lo_map["longitude"].values.astype(str),
- "latitude": lo_map["latitude"].values.astype(str),
- }
- # 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
- ),
- )
- }
+ # 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"
)
- return lo_map
+ # 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 dataset.drop_vars(vars_to_remove)
diff --git a/imap_processing/lo/lo_ancillary.py b/imap_processing/lo/lo_ancillary.py
new file mode 100644
index 0000000000..994b03f30c
--- /dev/null
+++ b/imap_processing/lo/lo_ancillary.py
@@ -0,0 +1,55 @@
+"""Ancillary file reading for IMAP-Lo processing."""
+
+from pathlib import Path
+
+import pandas as pd
+
+# convert the YYYYDDD datetime format directly upon reading
+_CONVERTERS = {
+ "YYYYDDD": lambda x: pd.to_datetime(str(x), format="%Y%j"),
+ "#YYYYDDD": lambda x: pd.to_datetime(str(x), format="%Y%j"),
+ "YYYYDDD_strt": lambda x: pd.to_datetime(str(x), format="%Y%j"),
+ "YYYYDDD_end": lambda x: pd.to_datetime(str(x), format="%Y%j"),
+}
+
+# Columns in the csv files to rename for consistency
+_RENAME_COLUMNS = {
+ "YYYYDDD": "Date",
+ "#YYYYDDD": "Date",
+ "#Comments": "Comments",
+ "YYYYDDD_strt": "StartDate",
+ "YYYYDDD_end": "EndDate",
+}
+
+
+def read_ancillary_file(ancillary_file: str | Path) -> pd.DataFrame:
+ """
+ Read a generic ancillary CSV file into a pandas DataFrame.
+
+ Parameters
+ ----------
+ ancillary_file : str or Path
+ Path to the ancillary CSV file.
+
+ Returns
+ -------
+ pd.DataFrame
+ DataFrame containing the ancillary data.
+ """
+ skiprows = None
+ if "esa-mode-lut" in str(ancillary_file):
+ # skip the first row which is a comment
+ skiprows = [0]
+ elif "geometric-factor" in str(ancillary_file):
+ # skip the rows with comment headers indicating Hi_Res and Hi_Thr
+ skiprows = [1, 38]
+ df = pd.read_csv(ancillary_file, converters=_CONVERTERS, skiprows=skiprows)
+ df = df.rename(columns=_RENAME_COLUMNS)
+
+ if "geometric-factor" in str(ancillary_file):
+ # Add an ESA mode column based on the known structure of the file.
+ # The first 36 rows are ESA mode 0 (HiRes), the second 36 are ESA mode 1 (HiThr)
+ df["esa_mode"] = 0
+ df.loc[36:, "esa_mode"] = 1
+
+ return df
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 cc8de6f914..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(
@@ -328,6 +328,7 @@ def generate_dataset(
global_attributes = attribute_manager.get_global_attributes(logical_file_id)
global_attributes["is_mago"] = str(bool(single_file_l1a.is_mago))
global_attributes["is_active"] = str(bool(single_file_l1a.is_active))
+ global_attributes["all_vectors_primary"] = single_file_l1a.all_vectors_primary()
global_attributes["vectors_per_second"] = (
single_file_l1a.vectors_per_second_attribute()
)
diff --git a/imap_processing/mag/l1a/mag_l1a_data.py b/imap_processing/mag/l1a/mag_l1a_data.py
index de114a773d..ca360490fc 100644
--- a/imap_processing/mag/l1a/mag_l1a_data.py
+++ b/imap_processing/mag/l1a/mag_l1a_data.py
@@ -15,6 +15,7 @@
MAX_COMPRESSED_VECTOR_BITS,
MAX_FINE_TIME,
RANGE_BIT_WIDTH,
+ PrimarySensor,
)
from imap_processing.spice.time import met_to_ttj2000ns
@@ -204,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.
@@ -220,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
-------
@@ -241,28 +263,36 @@ class MagL1a:
twos_complement()
update_compression_array()
vectors_per_second_attribute()
+ all_vectors_primary()
"""
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
@@ -270,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:
@@ -283,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
@@ -315,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(
@@ -1006,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
@@ -1117,3 +1177,27 @@ def vectors_per_second_attribute(self) -> str:
last_vectors_per_second = vecsec
return output_str
+
+ def all_vectors_primary(self) -> bool:
+ """
+ Check if all vectors in the file are from the primary sensor.
+
+ For MAGO datasets, this checks if MAGO was consistently the primary sensor
+ across all packets. For MAGI datasets, this checks if MAGI was consistently
+ the primary sensor across all packets.
+
+ Returns
+ -------
+ bool
+ True if all vectors are from the primary sensor across all packets,
+ False otherwise.
+ """
+ expected_primary_value = (
+ PrimarySensor.MAGO.value if self.is_mago else PrimarySensor.MAGI.value
+ )
+
+ for _, packet in self.packet_definitions.items():
+ if packet.mago_is_primary != expected_primary_value:
+ return False
+
+ return True
diff --git a/imap_processing/mag/l1b/mag_l1b.py b/imap_processing/mag/l1b/mag_l1b.py
index e85ae9efb3..d18ce6177d 100644
--- a/imap_processing/mag/l1b/mag_l1b.py
+++ b/imap_processing/mag/l1b/mag_l1b.py
@@ -74,7 +74,6 @@ def mag_l1b(
calibration_matrix, time_shift = retrieve_matrix_from_l1b_calibration(
calibration_dataset, day_to_process, is_mago
)
- print(f"Using calibration matrix: {calibration_matrix}")
output_dataset = mag_l1b_processing(
input_dataset, calibration_matrix, time_shift, mag_attributes, source
@@ -182,6 +181,9 @@ def mag_l1b_processing(
try:
global_attributes["is_mago"] = input_dataset.attrs["is_mago"]
global_attributes["is_active"] = input_dataset.attrs["is_active"]
+ global_attributes["all_vectors_primary"] = input_dataset.attrs[
+ "all_vectors_primary"
+ ]
global_attributes["vectors_per_second"] = timeshift_vectors_per_second(
input_dataset.attrs["vectors_per_second"], time_shift
)
@@ -245,7 +247,6 @@ def retrieve_matrix_from_l1b_calibration(
The calibration matrix and time shift. These can be passed directly into
update_vector, calibrate_vector, and shift_time.
"""
- print(f"Finding data for day {day}")
if is_mago:
calibration_matrix = calibration_dataset.sel(epoch=day)["MFOTOURFO"]
time_shift = calibration_dataset.sel(epoch=day)["OTS"]
@@ -397,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
@@ -425,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 7cce5bf2b1..717e53cdb1 100644
--- a/imap_processing/mag/l1c/interpolation_methods.py
+++ b/imap_processing/mag/l1c/interpolation_methods.py
@@ -3,7 +3,6 @@
import logging
from enum import Enum
-from typing import Optional
import numpy as np
from scipy.interpolate import make_interp_spline
@@ -34,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
@@ -44,9 +45,10 @@ def linear(
input_vectors: np.ndarray,
input_timestamps: np.ndarray,
output_timestamps: np.ndarray,
- input_rate: Optional[VecSec] = None,
- output_rate: Optional[VecSec] = None,
-) -> np.ndarray:
+ input_rate: VecSec | None = None,
+ output_rate: VecSec | None = None,
+ extrapolate: bool = False,
+) -> tuple[np.ndarray, np.ndarray]:
"""
Linear interpolation of input vectors to output timestamps.
@@ -64,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
-------
@@ -71,18 +76,21 @@ 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(
input_vectors: np.ndarray,
input_timestamps: np.ndarray,
output_timestamps: np.ndarray,
- input_rate: Optional[VecSec] = None,
- output_rate: Optional[VecSec] = None,
-) -> np.ndarray:
+ input_rate: VecSec | None = None,
+ output_rate: VecSec | None = None,
+) -> tuple[np.ndarray, np.ndarray]:
"""
Quadratic interpolation of input vectors to output timestamps.
@@ -107,17 +115,20 @@ 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(
input_vectors: np.ndarray,
input_timestamps: np.ndarray,
output_timestamps: np.ndarray,
- input_rate: Optional[VecSec] = None,
- output_rate: Optional[VecSec] = None,
-) -> np.ndarray:
+ input_rate: VecSec | None = None,
+ output_rate: VecSec | None = None,
+) -> tuple[np.ndarray, np.ndarray]:
"""
Cubic interpolation of input vectors to output timestamps.
@@ -142,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:
@@ -175,8 +189,8 @@ def cic_filter(
input_vectors: np.ndarray,
input_timestamps: np.ndarray,
output_timestamps: np.ndarray,
- input_rate: Optional[VecSec],
- output_rate: Optional[VecSec],
+ input_rate: VecSec | None,
+ output_rate: VecSec | None,
):
"""
Apply CIC filter to data before interpolating.
@@ -230,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
@@ -242,9 +258,9 @@ def linear_filtered(
input_vectors: np.ndarray,
input_timestamps: np.ndarray,
output_timestamps: np.ndarray,
- input_rate: Optional[VecSec] = None,
- output_rate: Optional[VecSec] = None,
-) -> np.ndarray:
+ input_rate: VecSec | None = None,
+ output_rate: VecSec | None = None,
+) -> tuple[np.ndarray, np.ndarray]:
"""
Linear filtered interpolation of input vectors to output timestamps.
@@ -271,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
)
@@ -281,9 +303,9 @@ def quadratic_filtered(
input_vectors: np.ndarray,
input_timestamps: np.ndarray,
output_timestamps: np.ndarray,
- input_rate: Optional[VecSec] = None,
- output_rate: Optional[VecSec] = None,
-) -> np.ndarray:
+ input_rate: VecSec | None = None,
+ output_rate: VecSec | None = None,
+) -> tuple[np.ndarray, np.ndarray]:
"""
Quadratic filtered interpolation of input vectors to output timestamps.
@@ -310,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
)
@@ -320,9 +345,9 @@ def cubic_filtered(
input_vectors: np.ndarray,
input_timestamps: np.ndarray,
output_timestamps: np.ndarray,
- input_rate: Optional[VecSec] = None,
- output_rate: Optional[VecSec] = None,
-) -> np.ndarray:
+ input_rate: VecSec | None = None,
+ output_rate: VecSec | None = None,
+) -> tuple[np.ndarray, np.ndarray]:
"""
Cubic filtered interpolation of input vectors to output timestamps.
@@ -349,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 b4316a36c1..885f1bd9c8 100644
--- a/imap_processing/mag/l1c/mag_l1c.py
+++ b/imap_processing/mag/l1c/mag_l1c.py
@@ -1,21 +1,26 @@
"""MAG L1C processing module."""
import logging
-from typing import Optional
import numpy as np
import xarray as xr
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:
"""
@@ -28,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
@@ -40,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
@@ -59,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)
@@ -123,16 +125,35 @@ 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"]
- global_attributes["missing_sequences"] = normal_mode_dataset.attrs[
+ 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 = 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
+ if burst_mode_dataset is not None:
+ burst_all_primary = burst_mode_dataset.attrs.get(
+ "all_vectors_primary", False
+ )
+
+ # Both datasets must have all vectors primary for the combined result to be True
+ global_attributes["all_vectors_primary"] = (
+ normal_all_primary and burst_all_primary
+ )
+
+ 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
@@ -155,15 +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],
@@ -176,14 +206,14 @@ def mag_l1c(
completed_timeline[:, 5],
name="generated_flag",
dims=["epoch"],
- # attrs=attribute_manager.get_variable_attributes("generated_flag_attrs"),
+ attrs=attribute_manager.get_variable_attributes("generated_flag_attrs"),
)
return output_dataset
def select_datasets(
- first_input_dataset: xr.Dataset, second_input_dataset: Optional[xr.Dataset] = None
+ first_input_dataset: xr.Dataset, second_input_dataset: xr.Dataset | None = None
) -> tuple[xr.Dataset, xr.Dataset]:
"""
Given one or two datasets, assign one to norm and one to burst.
@@ -243,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.
@@ -271,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)))
+
+ 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)
+ 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
)
@@ -301,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.
@@ -313,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)
@@ -372,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
@@ -382,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
@@ -406,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,
@@ -439,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):
@@ -454,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
@@ -461,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
----------
@@ -470,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
+
+ # 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]
- full_timeline = np.concatenate((full_timeline, epoch_data[last_gap:]))
+ 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: Optional[dict] = 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.
@@ -512,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
@@ -520,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
-------
@@ -528,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
@@ -572,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, :] = [
@@ -590,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
@@ -598,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.
@@ -640,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 ff82d0b23c..f51f799111 100644
--- a/imap_processing/mag/l1d/mag_l1d.py
+++ b/imap_processing/mag/l1d/mag_l1d.py
@@ -9,7 +9,7 @@
from imap_processing.mag.l2.mag_l2_data import ValidFrames
-def mag_l1d(
+def mag_l1d( # noqa: PLR0912
science_data: list[xr.Dataset],
calibration_dataset: xr.Dataset,
day_to_process: np.datetime64,
@@ -45,16 +45,18 @@ def mag_l1d(
input_mago_burst = None
for dataset in science_data:
source = dataset.attrs.get("Logical_source", "")
- if "norm-magi" in source:
- input_magi_norm = dataset
- elif "norm-mago" in source:
- input_mago_norm = dataset
- elif "burst-magi" in source:
- input_magi_burst = dataset
- elif "burst-mago" in source:
- input_mago_burst = dataset
- else:
- raise ValueError(f"Input data has invalid logical source {source}")
+ instrument_mode = source.split("_")[-1]
+ match instrument_mode:
+ case "norm-magi":
+ input_magi_norm = dataset
+ case "norm-mago":
+ input_mago_norm = dataset
+ case "burst-magi":
+ input_magi_burst = dataset
+ case "burst-mago":
+ input_mago_burst = dataset
+ case _:
+ raise ValueError(f"Input data has invalid logical source {source}")
if input_magi_norm is None or input_mago_norm is None:
raise ValueError(
@@ -72,10 +74,10 @@ def mag_l1d(
mago_vectors = input_mago_norm["vectors"].data[:, :3]
magi_vectors = input_magi_norm["vectors"].data[:, :3]
- # TODO: verify that MAGO is primary sensor for all vectors before applying
- # gradiometry
+ # Verify that MAGO is primary sensor for all vectors before applying gradiometry
+ 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")
@@ -95,12 +97,21 @@ def mag_l1d(
day=day,
)
+ # Nominally, this is expected to create MAGO data. However, if the configuration
+ # setting for always_output_mago is set to False, it will create MAGI data.
+
l1d_norm.rotate_frame(ValidFrames.SRF)
norm_srf_dataset = l1d_norm.generate_dataset(attributes, day_to_process)
l1d_norm.rotate_frame(ValidFrames.DSRF)
norm_dsrf_dataset = l1d_norm.generate_dataset(attributes, day_to_process)
+ l1d_norm.rotate_frame(ValidFrames.GSE)
+ norm_gse_dataset = l1d_norm.generate_dataset(attributes, day_to_process)
+ l1d_norm.rotate_frame(ValidFrames.RTN)
+ norm_rtn_dataset = l1d_norm.generate_dataset(attributes, day_to_process)
output_datasets.append(norm_srf_dataset)
output_datasets.append(norm_dsrf_dataset)
+ output_datasets.append(norm_gse_dataset)
+ output_datasets.append(norm_rtn_dataset)
if input_mago_burst is not None and input_magi_burst is not None:
# If burst data is provided, use it to create the burst L1d dataset
@@ -122,12 +133,43 @@ def mag_l1d(
spin_offsets=l1d_norm.spin_offsets,
day=day,
)
+
+ # TODO: frame specific attributes may be required
l1d_burst.rotate_frame(ValidFrames.SRF)
burst_srf_dataset = l1d_burst.generate_dataset(attributes, day_to_process)
l1d_burst.rotate_frame(ValidFrames.DSRF)
burst_dsrf_dataset = l1d_burst.generate_dataset(attributes, day_to_process)
+ l1d_burst.rotate_frame(ValidFrames.GSE)
+ burst_gse_dataset = l1d_burst.generate_dataset(attributes, day_to_process)
+ l1d_burst.rotate_frame(ValidFrames.RTN)
+ burst_rtn_dataset = l1d_burst.generate_dataset(attributes, day_to_process)
output_datasets.append(burst_srf_dataset)
output_datasets.append(burst_dsrf_dataset)
+ output_datasets.append(burst_gse_dataset)
+ output_datasets.append(burst_rtn_dataset)
+
+ # Output ancillary files
+ # 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"
+ 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"
+ )
+ output_datasets.append(gradiometry_dataset)
+
+ # Also add burst gradiometry offsets if burst data was processed
+ if input_mago_burst is not None and input_magi_burst is not None:
+ 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"
+ )
+ output_datasets.append(burst_gradiometry_dataset)
- # TODO: Output ancillary files
return output_datasets
diff --git a/imap_processing/mag/l1d/mag_l1d_data.py b/imap_processing/mag/l1d/mag_l1d_data.py
index 55b3021ceb..e52546b580 100644
--- a/imap_processing/mag/l1d/mag_l1d_data.py
+++ b/imap_processing/mag/l1d/mag_l1d_data.py
@@ -1,17 +1,23 @@
# 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
+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 FILLVAL, DataMode
from imap_processing.mag.l1c.interpolation_methods import linear
from imap_processing.mag.l2.mag_l2 import retrieve_matrix_from_l2_calibration
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_et, ttj2000ns_to_met
+
+logger = logging.getLogger(__name__)
@dataclass
@@ -57,7 +63,7 @@ class MagL1dConfiguration:
mago_calibration: np.ndarray
magi_calibration: np.ndarray
spin_count_calibration: int
- quality_flag_threshold: np.float64
+ quality_flag_threshold: float
spin_average_application_factor: np.float64
gradiometer_factor: np.ndarray
apply_gradiometry: bool = True
@@ -144,14 +150,13 @@ class MagL1d(MagL2L1dBase): # type: ignore[misc]
truncate the data to exactly 24 hours.
"""
- # TODO Quality flags
- # TODO generate and output ancillary files
magi_vectors: np.ndarray
magi_range: np.ndarray
magi_epoch: np.ndarray
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:
"""
@@ -165,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(
@@ -182,7 +193,7 @@ def __post_init__(self, day: np.datetime64) -> None:
self.vectors = self.apply_spin_offsets(
self.spin_offsets,
- self.epoch,
+ self.epoch, # type: ignore[has-type]
self.vectors,
self.config.spin_average_application_factor,
)
@@ -198,7 +209,11 @@ def __post_init__(self, day: np.datetime64) -> None:
if self.config.apply_gradiometry:
self.gradiometry_offsets = self.calculate_gradiometry_offsets(
- self.vectors, self.epoch, self.magi_vectors, self.magi_epoch
+ self.vectors,
+ self.epoch, # type: ignore[has-type]
+ self.magi_vectors,
+ self.magi_epoch,
+ self.config.quality_flag_threshold,
)
self.vectors = self.apply_gradiometry_offsets(
self.gradiometry_offsets, self.vectors, self.config.gradiometer_factor
@@ -207,6 +222,55 @@ def __post_init__(self, day: np.datetime64) -> None:
self.magnitude = MagL2L1dBase.calculate_magnitude(vectors=self.vectors)
self.is_l1d = True
+ def generate_dataset(
+ self,
+ attribute_manager: ImapCdfAttributes,
+ day: np.datetime64,
+ ) -> xr.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, and to construct
+ the logical_source_id for L1D files.
+
+ Parameters
+ ----------
+ attribute_manager : ImapCdfAttributes
+ CDF attributes object for the correct level.
+ day : np.datetime64
+ The 24 hour day to process, as a numpy datetime format.
+
+ Returns
+ -------
+ xr.Dataset
+ Complete dataset ready to write to CDF file.
+ """
+ always_output_mago = configuration.ALWAYS_OUTPUT_MAGO
+
+ if not always_output_mago:
+ # Swap vectors and epochs to use MAGI data instead of MAGO
+ original_vectors: np.ndarray = self.vectors.copy()
+ original_epoch: np.ndarray = self.epoch.copy() # type: ignore[has-type]
+ original_range: np.ndarray = self.range.copy() # type: ignore[has-type]
+
+ self.vectors = self.magi_vectors # type: ignore[no-redef]
+ self.epoch = self.magi_epoch # type: ignore[no-redef]
+ self.range = self.magi_range # type: ignore[no-redef]
+
+ # Call parent generate_dataset method with L1D data level
+ dataset = super().generate_dataset(attribute_manager, day)
+
+ # Restore original vectors for any further processing
+ self.vectors = original_vectors
+ self.epoch = original_epoch
+ self.range = original_range
+ else:
+ # Use MAGO data (default behavior)
+ dataset = super().generate_dataset(attribute_manager, day)
+
+ return dataset
+
def rotate_frame(self, end_frame: ValidFrames) -> None:
"""
Rotate the vectors to the desired frame.
@@ -219,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,
@@ -312,10 +419,10 @@ def apply_calibration_offset_single_vector(
The offset vector, shape (4,) where the last element is unchanged.
"""
# Offsets are in shape (sensor, range, axis)
- updated_vector = input_vector.copy().astype(np.int64)
+ 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:
@@ -348,64 +455,140 @@ def calculate_spin_offsets(self) -> xr.Dataset:
"Spin offsets can only be calculated in NORM mode and SRF frame."
)
- # TODO: get the spin numbers which correspond to the epoch values for output
- sc_spin_phase: np.ndarray = spin.get_spacecraft_spin_phase(self.epoch) # type: ignore
+ 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
- # TODO: currently fully skipping spins with no valid data (not including
- # them in the averaging OR IN SPIN COUNTING!) is this correct?
-
# first timestamp where spin phase is less than the previous value
# this is when the spin crosses zero
spin_starts = np.where(np.diff(sc_spin_phase) < 0)[0] + 1
- # if the value switches from nan to a number, that is also a spin start (for an
- # invalid spin)
- nan_to_number = (
- np.where(np.isnan(sc_spin_phase[:-1]) & ~np.isnan(sc_spin_phase[1:]))[0] + 1
- )
+ # if the value switches from nan to a number, or from a number to nan, that
+ # is also a spin start
+ nan_to_number = np.where(np.diff(np.isnan(sc_spin_phase)) != 0)[0] + 1
# find the places spins start while skipping over invalid or missing data
# (marked as nan by get_spacecraft_spin_phase)
spin_starts = np.sort(np.concatenate((spin_starts, nan_to_number)))
+ # Get the expected spin period from the spin table
+ # Convert to nanoseconds to match epoch
+ spin_data = spin.get_spin_data()
+ # Use the median spin period as the expected value
+ expected_spin = np.median(spin_data["spin_period_sec"]) * 1e9
+
+ paired_nans = nan_to_number.reshape(-1, 2)
+
+ for start_of_gap, end_of_gap in paired_nans:
+ # in nan_to_number, we have the start and end for every nan gap
+ # if this gap spans more than 1 spin period, we need to insert
+ # additional spin_starts into spin_starts.
+
+ gap_start_time = self.epoch[start_of_gap]
+ gap_end_time = self.epoch[end_of_gap]
+
+ # Calculate the number of spins in this gap
+ number_of_spins = int((gap_end_time - gap_start_time) // expected_spin)
+ if number_of_spins > 1:
+ # Insert new spin starts into spin_starts
+ for i in range(1, number_of_spins):
+ estimated_start = gap_start_time + i * expected_spin
+ new_spin_index = (np.abs(self.epoch - estimated_start)).argmin()
+
+ spin_starts = np.append(spin_starts, new_spin_index)
+
+ # Now spin_starts contains all the indices where spins begin, including
+ # estimating skipped or missing spins.
+ spin_starts = np.sort(spin_starts)
+
chunk_start = 0
offset_epochs = []
- x_avg = []
- y_avg = []
+ x_avg_calcs: list[np.float64] = []
+ y_avg_calcs: list[np.float64] = []
+ validity_start_times = []
+ validity_end_times = []
+ start_spin_counters = []
+ end_spin_counters = []
+
while chunk_start < len(spin_starts):
# Take self.spin_count_calibration number of spins and put them into a chunk
chunk_indices = spin_starts[
chunk_start : chunk_start + self.config.spin_count_calibration + 1
]
- chunk_start = chunk_start + self.config.spin_count_calibration
-
- # If we are in the end of the chunk, just grab all remaining data
- if chunk_start >= len(spin_starts):
- chunk_indices = np.append(chunk_indices, len(self.epoch))
+ chunk_start_idx = chunk_start
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])))
+ total_points = len(chunk_vectors)
+
# average the x and y axes (z is fixed, as the spin axis)
- # TODO: is z the correct axis here?
avg_x = np.nanmean(chunk_vectors[:, 0])
avg_y = np.nanmean(chunk_vectors[:, 1])
+ # Skip chunk if more than half of x or y data is NaN, or if we have less
+ # than half a spin.
+ # in this case, we should reuse the previous averages.
+ if (
+ x_valid_count <= total_points / 2
+ or y_valid_count <= total_points / 2
+ or total_points <= self.config.spin_count_calibration / 2
+ ):
+ avg_x = x_avg_calcs[-1] if x_avg_calcs else np.float64(FILLVAL)
+ avg_y = y_avg_calcs[-1] if y_avg_calcs else np.float64(FILLVAL)
+
if not np.isnan(avg_x) and not np.isnan(avg_y):
offset_epochs.append(chunk_epoch[0])
- x_avg.append(avg_x)
- y_avg.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])
+ validity_end_times.append(chunk_epoch[-1])
+
+ # Add spin counter information
+ start_spin_counters.append(chunk_start_idx)
+ end_spin_counters.append(
+ min(
+ chunk_start_idx + self.config.spin_count_calibration - 1,
+ len(spin_starts) - 1,
+ )
+ )
+
+ chunk_start = chunk_start + self.config.spin_count_calibration
spin_epoch_dataarray = xr.DataArray(np.array(offset_epochs))
spin_offsets = xr.Dataset(coords={"epoch": spin_epoch_dataarray})
- spin_offsets["x_offset"] = xr.DataArray(np.array(x_avg), dims=["epoch"])
- spin_offsets["y_offset"] = xr.DataArray(np.array(y_avg), dims=["epoch"])
+ spin_offsets["x_offset"] = xr.DataArray(np.array(x_avg_calcs), dims=["epoch"])
+ spin_offsets["y_offset"] = xr.DataArray(np.array(y_avg_calcs), dims=["epoch"])
+ spin_offsets["validity_start_time"] = xr.DataArray(
+ np.array(validity_start_times), dims=["epoch"]
+ )
+ spin_offsets["validity_end_time"] = xr.DataArray(
+ np.array(validity_end_times), dims=["epoch"]
+ )
+ spin_offsets["start_spin_counter"] = xr.DataArray(
+ np.array(start_spin_counters), dims=["epoch"]
+ )
+ spin_offsets["end_spin_counter"] = xr.DataArray(
+ np.array(end_spin_counters), dims=["epoch"]
+ )
return spin_offsets
@@ -462,7 +645,7 @@ def apply_spin_offsets(
if spin_offsets is None:
raise ValueError("No spin offsets calculated to apply.")
- output_vectors = np.full(vectors.shape, FILLVAL, dtype=np.int64)
+ output_vectors = np.full(vectors.shape, FILLVAL, dtype=np.float64)
for index in range(spin_offsets["epoch"].data.shape[0] - 1):
timestamp = spin_offsets["epoch"].data[index]
@@ -483,7 +666,6 @@ def apply_spin_offsets(
if not np.any(mask):
continue
- # TODO: should vectors be a float?
x_offset = (
spin_offsets["x_offset"].data[index] * spin_average_application_factor
)
@@ -504,6 +686,7 @@ def calculate_gradiometry_offsets(
mago_epoch: np.ndarray,
magi_vectors: np.ndarray,
magi_epoch: np.ndarray,
+ quality_flag_threshold: float = np.inf,
) -> xr.Dataset:
"""
Calculate the gradiometry offsets between MAGo and MAGi.
@@ -525,6 +708,10 @@ def calculate_gradiometry_offsets(
The MAGi vectors, shape (N, 3).
magi_epoch : np.ndarray
The MAGi epoch values, shape (N,).
+ quality_flag_threshold : np.float64, optional
+ Threshold for quality flags. If the magnitude of gradiometer offset
+ exceeds this threshold, quality flag will be set. Default is np.inf
+ (no quality flags set).
Returns
-------
@@ -532,19 +719,33 @@ def calculate_gradiometry_offsets(
The gradiometer offsets dataset, with variables:
- epoch: the timestamp of the MAGo data
- gradiometer_offsets: the offset values (MAGi - MAGo) for each axis
+ - 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
+ # Calculate magnitude of gradiometer offset for each vector
+ magnitude = np.linalg.norm(diff, axis=1)
+
+ # Set quality flags: 0 = good data (below threshold), 1 = bad data
+ quality_flags = (magnitude > quality_flag_threshold).astype(int)
+
grad_epoch = xr.DataArray(mago_epoch, dims=["epoch"])
direction = xr.DataArray(["x", "y", "z"], dims=["axis"])
grad_ds = xr.Dataset(coords={"epoch": grad_epoch, "direction": direction})
grad_ds["gradiometer_offsets"] = xr.DataArray(diff, dims=["epoch", "direction"])
+ grad_ds["gradiometer_offset_magnitude"] = xr.DataArray(
+ magnitude, dims=["epoch"]
+ )
+ grad_ds["quality_flags"] = xr.DataArray(quality_flags, dims=["epoch"])
return grad_ds
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 d5a7e4f48d..a12d1ce886 100644
--- a/imap_processing/mag/l2/mag_l2_data.py
+++ b/imap_processing/mag/l2/mag_l2_data.py
@@ -7,22 +7,119 @@
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
from imap_processing.spice.time import (
et_to_ttj2000ns,
str_to_et,
+ ttj2000ns_to_et,
)
class ValidFrames(Enum):
"""SPICE reference frames for output."""
- MAG = SpiceFrame.IMAP_MAG
- DSRF = SpiceFrame.IMAP_DPS
- SRF = SpiceFrame.IMAP_SPACECRAFT
- # TODO: include RTN and GSE as valid frames
+ """
+ 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)
@@ -54,7 +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
@@ -65,7 +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,
@@ -93,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",
@@ -124,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(
@@ -147,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 = (
@@ -172,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
@@ -208,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,
@@ -301,27 +419,33 @@ def rotate_frame(self, end_frame: ValidFrames) -> None:
The frame to rotate the data to. Must be one of the ValidFrames enum
values.
"""
- self.vectors = frame_transform(
- self.epoch,
+ if self.epoch_et is None:
+ self.epoch_et = ttj2000ns_to_et(self.epoch)
+ 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 3eefdbb592..e0c48df2bb 100644
--- a/imap_processing/quality_flags.py
+++ b/imap_processing/quality_flags.py
@@ -37,12 +37,16 @@ class ENAFlags(FlagNameMixin):
BADSPIN = 2**2 # bit 2, Bad spin
-class ImapDEUltraFlags(FlagNameMixin):
+class ImapDEOutliersUltraFlags(FlagNameMixin):
"""IMAP Ultra flags."""
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):
@@ -75,6 +79,21 @@ class ImapRatesUltraFlags(FlagNameMixin):
PARTIALSPIN = 2**2 # bit 2
+class ImapDEScatteringUltraFlags(FlagNameMixin):
+ """IMAP Ultra Scattering flags."""
+
+ NONE = CommonFlags.NONE
+ ABOVE_THRESHOLD = 2**0 # bit 0
+ 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."""
@@ -123,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 0e2b0603d7..1325609327 100644
--- a/imap_processing/spice/geometry.py
+++ b/imap_processing/spice/geometry.py
@@ -9,22 +9,22 @@
* Always return numpy arrays for vectorized calls.
"""
+import logging
import typing
from enum import IntEnum
-from typing import Union
import numpy as np
import numpy.typing as npt
import spiceypy
from numpy.typing import NDArray
-from imap_processing.spice.kernels import ensure_spice
+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
@@ -36,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")
@@ -44,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
@@ -62,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
@@ -82,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]),
@@ -100,10 +109,8 @@ class SpiceFrame(IntEnum):
}
-@typing.no_type_check
-@ensure_spice
def imap_state(
- et: Union[np.ndarray, float],
+ et: np.ndarray | float,
ref_frame: SpiceFrame = SpiceFrame.ECLIPJ2000,
abcorr: str = "NONE",
observer: SpiceBody = SpiceBody.SUN,
@@ -129,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
@@ -137,14 +144,71 @@ def imap_state(
return np.asarray(state)
+def get_instrument_mounting_az_el(instrument: SpiceFrame) -> np.ndarray:
+ """
+ Calculate the azimuth and elevation angle of instrument mounting.
+
+ Azimuth and elevation to instrument mounting in the spacecraft frame.
+ Azimuth is measured in degrees from the spacecraft x-axis. Elevation is measured
+ in degrees from the spacecraft x-y plane.
+
+ Parameters
+ ----------
+ instrument : SpiceFrame
+ Instrument to get the azimuth and elevation angles for.
+
+ Returns
+ -------
+ instrument_mounting_az_el : np.ndarray
+ 2-element array containing azimuth and elevation of the instrument
+ mounting in the spacecraft frame. Azimuth is measured in degrees from
+ the spacecraft x-axis. Elevation is measured in degrees from the
+ spacecraft x-y plane.
+ """
+ # Each instrument can have a unique basis vector in the instrument
+ # 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, 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_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]),
+ SpiceFrame.IMAP_HIT: np.array([0, 1, 0]),
+ SpiceFrame.IMAP_IDEX: np.array([0, 1, 0]),
+ SpiceFrame.IMAP_GLOWS: np.array([0, 0, -1]),
+ }
+
+ # Get the instrument mounting normal vector expressed in the spacecraft frame
+ # The reference frames are fixed, so the et argument can be fixed at 0
+ instrument_normal_sc = frame_transform(
+ 0, mounting_normal_vector[instrument], instrument, SpiceFrame.IMAP_SPACECRAFT
+ )
+ # Convert the cartesian coordinate to azimuth/elevation angles in degrees
+ return np.rad2deg(
+ spiceypy.recazl(instrument_normal_sc, azccw=True, elplsz=True)[1:]
+ )
+
+
def get_spacecraft_to_instrument_spin_phase_offset(instrument: SpiceFrame) -> float:
"""
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
- to S/C CS Transformations` in document `7516-0011_drw.pdf`. These fixed
- values will need to be updated based on calibration data or retrieved using
- SPICE and the latest IMAP frame kernel.
+ 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-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
----------
@@ -156,29 +220,32 @@ def get_spacecraft_to_instrument_spin_phase_offset(instrument: SpiceFrame) -> fl
spacecraft_to_instrument_spin_phase_offset : float
The spin phase offset from the spacecraft to the instrument.
"""
- # TODO: Implement retrieval from SPICE?
- offset_lookup = {
- SpiceFrame.IMAP_LO_BASE: 330 / 360,
- SpiceFrame.IMAP_HI_45: 255 / 360,
- SpiceFrame.IMAP_HI_90: 285 / 360,
- SpiceFrame.IMAP_ULTRA_45: 33 / 360,
- SpiceFrame.IMAP_ULTRA_90: 210 / 360,
- SpiceFrame.IMAP_SWAPI: 168 / 360,
- SpiceFrame.IMAP_IDEX: 90 / 360,
- SpiceFrame.IMAP_CODICE: 136 / 360,
- SpiceFrame.IMAP_HIT: 30 / 360,
- SpiceFrame.IMAP_SWE: 153 / 360,
- SpiceFrame.IMAP_GLOWS: 127 / 360,
- SpiceFrame.IMAP_MAG: 0 / 360,
+ phase_offset_lookup = {
+ # 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 offset_lookup[instrument]
+ return phase_offset_lookup[instrument]
def frame_transform(
- et: Union[float, npt.NDArray],
+ et: float | npt.NDArray,
position: npt.NDArray,
from_frame: SpiceFrame,
to_frame: SpiceFrame,
+ allow_spice_noframeconnect: bool = False,
) -> npt.NDArray:
"""
Transform an vector between reference frames (rotation only).
@@ -205,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
-------
@@ -237,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)
@@ -249,7 +321,7 @@ def frame_transform(
def frame_transform_az_el(
- et: Union[float, npt.NDArray],
+ et: float | npt.NDArray,
az_el: npt.NDArray,
from_frame: SpiceFrame,
to_frame: SpiceFrame,
@@ -264,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,
@@ -281,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)
@@ -298,16 +372,17 @@ def frame_transform_az_el(
return to_frame_az_el[..., 1:3]
-@typing.no_type_check
-@ensure_spice
def get_rotation_matrix(
- et: Union[float, npt.NDArray],
+ 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."
@@ -321,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
-------
@@ -328,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],
@@ -339,7 +437,7 @@ def get_rotation_matrix(
def instrument_pointing(
- et: Union[float, npt.NDArray],
+ et: float | npt.NDArray,
instrument: SpiceFrame,
to_frame: SpiceFrame,
cartesian: bool = False,
@@ -376,8 +474,99 @@ 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: Union[float, npt.NDArray],
+ et: float | npt.NDArray,
from_frame: SpiceFrame,
to_frame: SpiceFrame,
) -> npt.NDArray:
@@ -474,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
@@ -550,9 +739,9 @@ def cartesian_to_latitudinal(coords: NDArray, degrees: bool = True) -> NDArray:
def solar_longitude(
- et: Union[np.ndarray, float],
+ et: np.ndarray | float,
degrees: bool = True,
-) -> Union[float, npt.NDArray]:
+) -> float | npt.NDArray:
"""
Compute the solar longitude of the Imap Spacecraft.
diff --git a/imap_processing/spice/kernels.py b/imap_processing/spice/kernels.py
deleted file mode 100644
index 762aa98b4e..0000000000
--- a/imap_processing/spice/kernels.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""Functions that generate, furnish, and retrieve metadata from SPICE kernels."""
-
-import functools
-import logging
-import os
-from typing import Any, Callable, Optional, Union, overload
-
-import spiceypy
-from spiceypy.utils.exceptions import SpiceyError
-
-from imap_processing import imap_module_directory
-
-logger = logging.getLogger(__name__)
-
-
-# Declarations to help with typing. Taken from mypy documentation on
-# decorator-factories:
-# https://mypy.readthedocs.io/en/stable/generics.html#decorator-factories
-# Bare decorator usage
-@overload
-def ensure_spice(
- __func: Callable[..., Any],
-) -> Callable[..., Any]: ... # numpydoc ignore=GL08
-# Decorator with arguments
-@overload
-def ensure_spice(
- *, time_kernels_only: bool = False
-) -> Callable[[Callable[..., Any]], Callable[..., Any]]: ... # numpydoc ignore=GL08
-# Implementation
-def ensure_spice(
- __func: Optional[Callable[..., Any]] = None, *, time_kernels_only: bool = False
-) -> Union[Callable[..., Any], Callable[[Callable[..., Any]], Callable[..., Any]]]:
- """
- Decorator/wrapper that automatically furnishes SPICE kernels.
-
- Parameters
- ----------
- __func : Callable
- The function requiring SPICE that we are going to wrap if being used
- explicitly, otherwise None, in which case ensure_spice is being used,
- not as a function wrapper (see l2a_processing.py) but as a true
- decorator without an explicit function argument.
- time_kernels_only : bool
- Specify that we only need to furnish time kernels (if SPICE_METAKERNEL
- is set, we still just furnish that metakernel and assume the time
- kernels are included.
-
- Returns
- -------
- Callable
- Decorated function, with spice error handling.
-
- Notes
- -----
- Before trying to understand this piece of code, read this:
- https://stackoverflow.com/questions/5929107/decorators-with-parameters/60832711#60832711
-
- **Control flow overview:**
-
- 1. Try simply calling the wrapped function naively.
- * SUCCESS? Great! We're done.
- * SpiceyError? Go to step 2.
-
- 2. Furnish metakernel at SPICE_METAKERNEL
- * SUCCESS? Great, return the original function again (so it can be
- re-run).
- * KeyError? Seems like SPICE_METAKERNEL isn't set, no problem. Go to
- step 3.
-
- 3. Did we get the parameter time_kernels_only=True?
- * YES? We only need LSK and SCLK kernels to run this function. Go fetch
- those and furnish and return the original function (so it can be re-run).
- * NO? Dang. This is sort of the end of the line. Re-raise the error
- generated from the failed spiceypy function call but add a better
- message to it.
-
- Examples
- --------
- There are three ways to use this object
-
- 1. A decorator with no arguments
-
- >>> @ensure_spice
- ... def my_spicey_func(a, b):
- ... pass
-
- 2. A decorator with parameters. This is useful
- if we only need the latest SCLK and LSK kernels for the function involved.
-
- >>> @ensure_spice(time_kernels_only=True)
- ... def my_spicey_time_func(a, b):
- ... pass
-
- 3. An explicit wrapper function, providing a dynamically set value for
- parameters, e.g. time_kernels_only
-
- >>> wrapped = ensure_spice(spicey_func, time_kernels_only=True)
- ... result = wrapped(args, kwargs)
- """
-
- def _decorator(func: Callable[..., Callable]) -> Callable:
- """
- Decorate or wrap input function depending on how ensure_spice is used.
-
- Parameters
- ----------
- func : Callable
- The function to be decorated/wrapped.
-
- Returns
- -------
- Callable
- If used as a function wrapper, the decorated function is returned.
- """
-
- @functools.wraps(func)
- def wrapper_ensure_spice(*args: Any, **kwargs: Any) -> Any:
- """
- Wrap the function that ensure_spice is used on.
-
- Parameters
- ----------
- *args : list
- The positional arguments passed to the decorated function.
- **kwargs
- The keyword arguments passed to the decorated function.
-
- Returns
- -------
- Object
- Output from wrapped function.
- """
- try:
- # Step 1.
- return func(
- *args, **kwargs
- ) # Naive first try. Maybe SPICE is already furnished.
- except SpiceyError as spicey_err:
- try:
- # Step 2.
- if os.getenv("SPICE_METAKERNEL"):
- metakernel_path = os.getenv("SPICE_METAKERNEL")
- spiceypy.furnsh(metakernel_path)
- else:
- furnish_time_kernel()
- except KeyError:
- # TODO: An additional step that was used on EMUS was to get
- # a custom metakernel from the SDC API based on an input
- # time range.
- if time_kernels_only:
- # Step 3.
- # TODO: Decide if this is useful for IMAP. Possible
- # implementation could include downloading
- # the most recent leapsecond kernel from NAIF (see:
- # https://lasp.colorado.edu/nucleus/projects/LIBSDC/repos/libera_utils/browse/libera_utils/spice_utils.py
- # for LIBERA implementation of downloading and caching
- # kernels) and finding the most recent IMAP clock
- # kernel in EFS.
- raise NotImplementedError from spicey_err
- else:
- raise SpiceyError(
- "When calling a function requiring SPICE, we failed "
- "to load a metakernel. SPICE_METAKERNEL is not set,"
- "and time_kernels_only is not set to True"
- ) from spicey_err
- return func(*args, **kwargs)
-
- return wrapper_ensure_spice
-
- # Note: This return was originally implemented as a ternary operator, but
- # this caused mypy to fail due to this bug:
- # https://github.com/python/mypy/issues/4134
- if callable(__func):
- return _decorator(__func)
- else:
- return _decorator
-
-
-def furnish_time_kernel() -> None:
- """Furnish the time kernels."""
- spice_test_data_path = imap_module_directory / "tests/spice/test_data"
-
- # TODO: we need to load these kernels from EFS volumen that is
- # mounted to batch volume and extend this to generate metakernell
- # which is TBD.
- spiceypy.furnsh(str(spice_test_data_path / "imap_sclk_0000.tsc"))
- spiceypy.furnsh(str(spice_test_data_path / "naif0012.tls"))
diff --git a/imap_processing/spice/pointing_frame.py b/imap_processing/spice/pointing_frame.py
index 5289462ba9..9d3990fe40 100644
--- a/imap_processing/spice/pointing_frame.py
+++ b/imap_processing/spice/pointing_frame.py
@@ -1,7 +1,6 @@
"""Functions for retrieving repointing table data."""
import logging
-import typing
from collections.abc import Generator
from contextlib import contextmanager
from datetime import datetime, timezone
@@ -12,8 +11,8 @@
from imap_data_access import SPICEFilePath
from numpy.typing import NDArray
-from imap_processing.spice.geometry import SpiceFrame
-from imap_processing.spice.kernels import ensure_spice
+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,
@@ -24,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)
@@ -36,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
@@ -51,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]
@@ -95,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.
@@ -110,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)
@@ -140,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.
@@ -163,11 +171,11 @@ def write_pointing_frame_ck(
np.array([TICK_DURATION]),
)
+ logger.debug(f"Finished writing pointing attitude kernel: {pointing_kernel_path}")
+
-@typing.no_type_check
-@ensure_spice
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.
@@ -181,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
-------
@@ -199,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)
@@ -239,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.
@@ -270,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
@@ -283,20 +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
-@typing.no_type_check
-@ensure_spice
-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
----------
@@ -305,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 26c96c1aa1..c20d285620 100644
--- a/imap_processing/spice/repoint.py
+++ b/imap_processing/spice/repoint.py
@@ -2,14 +2,16 @@
import functools
import logging
+import re
from pathlib import Path
-from typing import Union
import numpy as np
import pandas as pd
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__)
@@ -113,7 +115,7 @@ def _load_repoint_data_with_cache(csv_path: Path) -> pd.DataFrame:
def interpolate_repoint_data(
- query_met_times: Union[float, npt.NDArray],
+ query_met_times: float | npt.NDArray,
) -> pd.DataFrame:
"""
Interpolate repointing data to the queried MET times.
@@ -194,3 +196,121 @@ def interpolate_repoint_data(
out_df["repoint_in_progress"] = query_met_times < out_df["repoint_end_met"].values
return out_df
+
+
+def get_pointing_times(met_time: float) -> tuple[float, float]:
+ """
+ Get the start and end MET times for the pointing that contains the query MET time.
+
+ Parameters
+ ----------
+ met_time : float
+ The MET time in a 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.
+ """
+ # Find the pointing start time by finding the repoint end time
+ repoint_df = interpolate_repoint_data(met_time)
+ pointing_start_met = repoint_df["repoint_end_met"].item()
+ # Find the pointing end time by finding the next repoint start time
+ repoint_df = get_repoint_data()
+ pointing_idx = repoint_df.index[
+ repoint_df["repoint_end_met"] == pointing_start_met
+ ][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 64a9f6ee92..20264e4739 100644
--- a/imap_processing/spice/spin.py
+++ b/imap_processing/spice/spin.py
@@ -4,7 +4,6 @@
import logging
from functools import reduce
from pathlib import Path
-from typing import Union
import numpy as np
import pandas as pd
@@ -55,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.
@@ -107,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,
},
@@ -126,10 +128,26 @@ 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
-def interpolate_spin_data(query_met_times: Union[float, npt.NDArray]) -> pd.DataFrame:
+def interpolate_spin_data(query_met_times: float | npt.NDArray) -> pd.DataFrame:
"""
Interpolate spin table data to the queried MET times.
@@ -160,11 +178,13 @@ def interpolate_spin_data(query_met_times: Union[float, npt.NDArray]) -> pd.Data
# 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:
@@ -181,15 +201,19 @@ def interpolate_spin_data(query_met_times: Union[float, npt.NDArray]) -> pd.Data
# >>> 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()
- # Calculate spin phase
- spin_phases = (query_met_times - out_df["spin_start_met"].values) / out_df[
- "spin_period_sec"
- ].values
+ # Get the precomputed actual spin period for each query time
+ spin_periods_for_query = actual_spin_periods[last_spin_indices]
+
+ # 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).
@@ -213,10 +237,33 @@ def interpolate_spin_data(query_met_times: Union[float, npt.NDArray]) -> pd.Data
return out_df
+def get_spin_number(met_time: float | npt.NDArray) -> int | npt.NDArray:
+ """
+ Get the spin number for the input query time.
+
+ The spin number is the index of the spin table row that contains the
+ spin data for the input query time.
+
+ Parameters
+ ----------
+ met_time : float or np.ndarray
+ Query time in Mission Elapsed Time (MET).
+
+ Returns
+ -------
+ spin_number : int or np.ndarray
+ Spin number for the input query time.
+ """
+ spin_df = interpolate_spin_data(met_time)
+ 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(
- spin_phases: Union[float, npt.NDArray],
+ spin_phases: float | npt.NDArray,
degrees: bool = False,
-) -> Union[float, npt.NDArray]:
+) -> float | npt.NDArray:
"""
Convert spin_phases to radians or degrees.
@@ -249,8 +296,8 @@ def get_spin_angle(
def get_spacecraft_spin_phase(
- query_met_times: Union[float, npt.NDArray],
-) -> Union[float, npt.NDArray]:
+ query_met_times: float | npt.NDArray,
+) -> float | npt.NDArray:
"""
Get the spacecraft spin phase for the input query times.
@@ -274,8 +321,8 @@ def get_spacecraft_spin_phase(
def get_instrument_spin_phase(
- query_met_times: Union[float, npt.NDArray], instrument: SpiceFrame
-) -> Union[float, npt.NDArray]:
+ query_met_times: float | npt.NDArray, instrument: SpiceFrame
+) -> float | npt.NDArray:
"""
Get the instrument spin phase for the input query times.
diff --git a/imap_processing/spice/time.py b/imap_processing/spice/time.py
index 08ad709cfd..e4baebf625 100644
--- a/imap_processing/spice/time.py
+++ b/imap_processing/spice/time.py
@@ -3,14 +3,12 @@
import typing
from collections.abc import Collection, Iterable
from datetime import datetime
-from typing import Union
import numpy as np
import numpy.typing as npt
import spiceypy
from imap_processing.spice import IMAP_SC_ID
-from imap_processing.spice.kernels import ensure_spice
TICK_DURATION = 2e-5 # 20 microseconds as defined in imap_sclk_0000.tsc
@@ -103,7 +101,6 @@ def met_to_ttj2000ns(
@typing.no_type_check
-@ensure_spice
def ttj2000ns_to_et(tt_ns: npt.ArrayLike) -> npt.NDArray[float]:
"""
Convert TT J2000 epoch nanoseconds to TDB J2000 epoch seconds.
@@ -131,7 +128,6 @@ def ttj2000ns_to_et(tt_ns: npt.ArrayLike) -> npt.NDArray[float]:
@typing.no_type_check
-@ensure_spice
def et_to_ttj2000ns(et: npt.ArrayLike) -> npt.NDArray[float]:
"""
Convert TDB J2000 epoch seconds to TT J2000 epoch nanoseconds.
@@ -157,7 +153,6 @@ def et_to_ttj2000ns(et: npt.ArrayLike) -> npt.NDArray[float]:
@typing.no_type_check
-@ensure_spice(time_kernels_only=True)
def met_to_utc(met: npt.ArrayLike, precision: int = 9) -> npt.NDArray[str]:
"""
Convert mission elapsed time (MET) to UTC.
@@ -184,7 +179,7 @@ def met_to_utc(met: npt.ArrayLike, precision: int = 9) -> npt.NDArray[str]:
def met_to_datetime64(
met: npt.ArrayLike,
-) -> Union[np.datetime64, npt.NDArray[np.datetime64]]:
+) -> np.datetime64 | npt.NDArray[np.datetime64]:
"""
Convert mission elapsed time (MET) to datetime.datetime.
@@ -203,7 +198,7 @@ def met_to_datetime64(
def et_to_datetime64(
et: npt.ArrayLike,
-) -> Union[np.datetime64, npt.NDArray[np.datetime64]]:
+) -> np.datetime64 | npt.NDArray[np.datetime64]:
"""
Convert ET to numpy datetime64.
@@ -221,10 +216,9 @@ def et_to_datetime64(
@typing.no_type_check
-@ensure_spice
def et_to_met(
- et: Union[float, Collection[float]],
-) -> Union[float, np.ndarray]:
+ et: float | Collection[float],
+) -> float | np.ndarray:
"""
Convert ephemeris time to mission elapsed time (MET).
@@ -272,10 +266,9 @@ def ttj2000ns_to_met(
@typing.no_type_check
-@ensure_spice
def sct_to_et(
- sclk_ticks: Union[float, Collection[float]],
-) -> Union[float, np.ndarray]:
+ sclk_ticks: float | Collection[float],
+) -> float | np.ndarray:
"""
Convert encoded spacecraft clock "ticks" to ephemeris time.
@@ -298,10 +291,9 @@ def sct_to_et(
@typing.no_type_check
-@ensure_spice
def sct_to_ttj2000s(
- sclk_ticks: Union[float, Iterable[float]],
-) -> Union[float, np.ndarray]:
+ sclk_ticks: float | Iterable[float],
+) -> float | np.ndarray:
"""
Convert encoded spacecraft clock "ticks" to terrestrial time (TT).
@@ -330,10 +322,9 @@ def conversion(sclk_ticks): # numpydoc ignore=GL08
@typing.no_type_check
-@ensure_spice
def str_to_et(
- time_str: Union[str, Iterable[str]],
-) -> Union[float, np.ndarray]:
+ time_str: str | Iterable[str],
+) -> float | np.ndarray:
"""
Convert string to ephemeris time.
@@ -356,13 +347,12 @@ def str_to_et(
@typing.no_type_check
-@ensure_spice
def et_to_utc(
- et: Union[float, Iterable[float]],
+ et: float | Iterable[float],
format_str: str = "ISOC",
precision: int = 3,
utclen: int = 24,
-) -> Union[str, np.ndarray]:
+) -> str | np.ndarray:
"""
Convert ephemeris time to UTC.
@@ -417,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 dee82a2a7b..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
@@ -138,7 +140,7 @@ def decompress_count(
# SWAPI suggested using big value to indicate overflow.
new_count[compressed_indices & (count_data == 0xFFFF)] = np.iinfo(np.int32).max
- return new_count
+ return (new_count).astype(np.float32)
def find_sweep_starts(packets: xr.Dataset) -> npt.NDArray:
@@ -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
@@ -474,6 +476,12 @@ def process_swapi_science(
swp_scem_counts = decompress_count(raw_scem_count, scem_compression_flags)
swp_coin_counts = decompress_count(raw_coin_count, coin_compression_flags)
+ # Fill first index of 72 steps with nan value per
+ # SWAPI team's instruction. nan helps with plotting.
+ swp_pcem_counts[:, 0] = np.nan
+ swp_scem_counts[:, 0] = np.nan
+ swp_coin_counts[:, 0] = np.nan
+
# ====================================================
# Load the CDF attributes
# ====================================================
@@ -484,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
@@ -540,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
@@ -562,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,
@@ -600,17 +612,17 @@ def process_swapi_science(
)
dataset["swp_pcem_counts"] = xr.DataArray(
- np.array(swp_pcem_counts, dtype=np.uint16),
+ swp_pcem_counts,
dims=["epoch", "esa_step"],
attrs=cdf_manager.get_variable_attributes("pcem_counts"),
)
dataset["swp_scem_counts"] = xr.DataArray(
- np.array(swp_scem_counts, dtype=np.uint16),
+ swp_scem_counts,
dims=["epoch", "esa_step"],
attrs=cdf_manager.get_variable_attributes("scem_counts"),
)
dataset["swp_coin_counts"] = xr.DataArray(
- np.array(swp_coin_counts, dtype=np.uint16),
+ swp_coin_counts,
dims=["epoch", "esa_step"],
attrs=cdf_manager.get_variable_attributes("coin_counts"),
)
@@ -620,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"),
@@ -644,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"),
@@ -655,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"),
@@ -721,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.
@@ -729,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
-------
@@ -748,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")
@@ -764,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 2f454b419b..6065102af6 100644
--- a/imap_processing/swapi/l2/swapi_l2.py
+++ b/imap_processing/swapi/l2/swapi_l2.py
@@ -8,11 +8,12 @@
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__)
-TIME_PER_BIN = 0.167 # seconds
+SWAPI_LIVETIME = 0.145 # seconds
def solve_full_sweep_energy(
@@ -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):
+ 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(
@@ -159,14 +160,12 @@ def swapi_l2(
To process science data to L2, we need to:
- convert counts to rates. This is done by dividing the counts by the
- TIME_PER_BIN time. TIME_PER_BIN is the exposure time per energy bin which is
- obtained by dividing the time for one complete sweep
- (12 s, coarse + fine sweep) by the total energy steps (72),
- i.e., TIME_PER_BIN = 12/72 = 0.167 s. This will be constant.
+ SWAPI_LIVETIME time. LIVETIME is data acquisition time. It will
+ be constant, SWAPI_LIVETIME = 0.145 s.
- update uncertainty. Calculate new uncertainty value using
- SWP_PCEM_ERR data from level one and divide by TIME_PER_BIN. Eg.
- SWP_PCEM_UNC = SWP_PCEM_ERR / TIME_PER_BIN
+ SWP_PCEM_ERR data from level one and divide by SWAPI_LIVETIME. Eg.
+ SWP_PCEM_UNC = SWP_PCEM_ERR / SWAPI_LIVETIME
Do the same for SCEM and COIN data.
Parameters
@@ -208,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"],
@@ -233,9 +238,14 @@ def swapi_l2(
]
# convert counts to rate
- l2_dataset["swp_pcem_rate"] = l1_dataset["swp_pcem_counts"] / TIME_PER_BIN
- l2_dataset["swp_scem_rate"] = l1_dataset["swp_scem_counts"] / TIME_PER_BIN
- l2_dataset["swp_coin_rate"] = l1_dataset["swp_coin_counts"] / TIME_PER_BIN
+ 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")
@@ -243,22 +253,22 @@ def swapi_l2(
# update uncertainty
l2_dataset["swp_pcem_rate_stat_uncert_plus"] = (
- l1_dataset["swp_pcem_counts_stat_uncert_plus"] / TIME_PER_BIN
+ l1_dataset["swp_pcem_counts_stat_uncert_plus"] / SWAPI_LIVETIME
)
l2_dataset["swp_pcem_rate_stat_uncert_minus"] = (
- l1_dataset["swp_pcem_counts_stat_uncert_minus"] / TIME_PER_BIN
+ l1_dataset["swp_pcem_counts_stat_uncert_minus"] / SWAPI_LIVETIME
)
l2_dataset["swp_scem_rate_stat_uncert_plus"] = (
- l1_dataset["swp_scem_counts_stat_uncert_plus"] / TIME_PER_BIN
+ l1_dataset["swp_scem_counts_stat_uncert_plus"] / SWAPI_LIVETIME
)
l2_dataset["swp_scem_rate_stat_uncert_minus"] = (
- l1_dataset["swp_scem_counts_stat_uncert_minus"] / TIME_PER_BIN
+ l1_dataset["swp_scem_counts_stat_uncert_minus"] / SWAPI_LIVETIME
)
l2_dataset["swp_coin_rate_stat_uncert_plus"] = (
- l1_dataset["swp_coin_counts_stat_uncert_plus"] / TIME_PER_BIN
+ l1_dataset["swp_coin_counts_stat_uncert_plus"] / SWAPI_LIVETIME
)
l2_dataset["swp_coin_rate_stat_uncert_minus"] = (
- l1_dataset["swp_coin_counts_stat_uncert_minus"] / TIME_PER_BIN
+ l1_dataset["swp_coin_counts_stat_uncert_minus"] / SWAPI_LIVETIME
)
# update attrs
l2_dataset[
diff --git a/imap_processing/swe/l1b/swe_l1b.py b/imap_processing/swe/l1b/swe_l1b.py
index 7e82dd273d..add5051b2b 100644
--- a/imap_processing/swe/l1b/swe_l1b.py
+++ b/imap_processing/swe/l1b/swe_l1b.py
@@ -2,7 +2,6 @@
import logging
from pathlib import Path
-from typing import Union
import numpy as np
import numpy.typing as npt
@@ -13,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 (
@@ -51,7 +51,7 @@ def get_esa_dataframe(esa_table_number: int) -> pd.DataFrame:
def deadtime_correction(
- counts: np.ndarray, acq_duration: Union[int, npt.NDArray]
+ counts: np.ndarray, acq_duration: int | npt.NDArray
) -> npt.NDArray:
"""
Calculate deadtime correction.
@@ -167,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
@@ -252,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.
@@ -264,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.
@@ -275,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:
@@ -381,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
@@ -439,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
@@ -471,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
@@ -648,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
@@ -696,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
# ---------------------------------------------------------------
@@ -755,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
)
@@ -768,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
# ------------------------------------------------------------------
@@ -786,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],
@@ -918,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 1e5ec584c8..36b9b13434 100644
--- a/imap_processing/tests/ancillary/test_ancillary_dataset_combiner.py
+++ b/imap_processing/tests/ancillary/test_ancillary_dataset_combiner.py
@@ -1,5 +1,8 @@
+import json
+import tempfile
from pathlib import Path
from unittest import mock
+from unittest.mock import patch
import numpy as np
import pytest
@@ -8,6 +11,7 @@
from imap_processing.ancillary.ancillary_dataset_combiner import (
AncillaryCombiner,
+ GlowsAncillaryCombiner,
MagAncillaryCombiner,
TimestampedData,
)
@@ -42,6 +46,14 @@ def mag_calibration_dataset():
return calibration_data
+@pytest.fixture
+def glows_ancillary_filepath():
+ imap_dir = Path(__file__).parent.parent.parent.parent
+ filepath = imap_dir / "imap_processing" / "glows" / "ancillary"
+
+ return filepath
+
+
@pytest.fixture
def ancillary_input():
input_example = AncillaryInput(
@@ -203,3 +215,275 @@ def test_no_end_date(mocks, mag_calibration_dataset):
assert np.array_equal(
output.combined_dataset["input_file_version"].data, expected_versions
)
+
+
+def test_glows_excluded_regions_combiner(glows_ancillary_filepath):
+ file_path = (
+ glows_ancillary_filepath
+ / "imap_glows_map-of-excluded-regions_20250923_v002.dat"
+ )
+
+ # Test the convert_file_to_dataset method directly
+ combiner = GlowsAncillaryCombiner(
+ [], "20250925"
+ ) # Empty list to avoid file parsing
+ dataset = combiner.convert_file_to_dataset(file_path)
+
+ assert dataset is not None
+ assert "ecliptic_longitude_deg" in dataset.data_vars
+ assert "ecliptic_latitude_deg" in dataset.data_vars
+ assert dataset["ecliptic_longitude_deg"].dims == ("region",)
+ 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"
+ )
+
+ # Test the convert_file_to_dataset method directly
+ combiner = GlowsAncillaryCombiner(
+ [], "20250925"
+ ) # Empty list to avoid file parsing
+ dataset = combiner.convert_file_to_dataset(file_path)
+
+ assert dataset is not None
+ assert "object_name" in dataset.data_vars
+ assert "ecliptic_longitude_deg" in dataset.data_vars
+ assert "ecliptic_latitude_deg" in dataset.data_vars
+ assert "angular_radius_for_masking" in dataset.data_vars
+ assert dataset["object_name"].dims == ("source",)
+
+
+def test_glows_suspected_transients_combiner(glows_ancillary_filepath):
+ file_path = (
+ glows_ancillary_filepath / "imap_glows_suspected-transients_20250923_v002.dat"
+ )
+
+ # Test the convert_file_to_dataset method directly
+ combiner = GlowsAncillaryCombiner(
+ [], "20250925"
+ ) # Empty list to avoid file parsing
+ dataset = combiner.convert_file_to_dataset(file_path)
+
+ assert dataset is not None
+ assert "l1b_unique_block_identifier" in dataset.data_vars
+ assert "histogram_mask_array" in dataset.data_vars
+ assert dataset["l1b_unique_block_identifier"].dims == ("time_block",)
+
+
+def test_glows_exclusions_by_instr_team_combiner(glows_ancillary_filepath):
+ file_path = (
+ glows_ancillary_filepath
+ / "imap_glows_exclusions-by-instr-team_20250923_v002.dat"
+ )
+
+ # Test the convert_file_to_dataset method directly
+ combiner = GlowsAncillaryCombiner(
+ [], "20250925"
+ ) # Empty list to avoid file parsing
+ dataset = combiner.convert_file_to_dataset(file_path)
+
+ assert dataset is not None
+ assert "l1b_unique_block_identifier" in dataset.data_vars
+ assert "histogram_mask_array" in dataset.data_vars
+ assert dataset["l1b_unique_block_identifier"].dims == ("time_block",)
+
+ # Test with mocked construct_path to simulate full file path workflow
+ with patch(
+ "imap_data_access.AncillaryFilePath.construct_path", return_value=str(file_path)
+ ):
+ combiner = GlowsAncillaryCombiner(
+ ["imap_glows_exclusions-by-instr-team_20250923_v002.dat"], "20250925"
+ )
+ assert len(combiner.timestamped_data) == 1
+ 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")
+ assert len(combiner.timestamped_data) == 0
+ assert len(combiner.combined_dataset.data_vars) == 0
+
+
+def test_ancillary_combiner_string_date():
+ """Test AncillaryCombiner with string date format."""
+ with mock.patch(
+ "imap_processing.ancillary.ancillary_dataset_combiner.cdf_to_xarray"
+ ) as mock_cdf:
+ mock_dataset = xr.Dataset({"test_var": ([], 42)})
+ mock_cdf.return_value = mock_dataset
+
+ input_files = ["imap_mag_l2-calibration-matrices_20251017_v001.cdf"]
+ combiner = AncillaryCombiner(input_files, "20251031") # String date
+
+ assert combiner.expected_end_date == np.datetime64("2025-10-31")
+
+
+def test_dataset_with_epoch_dimension_error(mocks, mag_calibration_dataset):
+ """Test error when input dataset has epoch dimension."""
+ # Create a dataset with epoch dimension
+ dataset_with_epoch = mag_calibration_dataset.copy()
+ dataset_with_epoch = dataset_with_epoch.expand_dims("epoch")
+
+ mocks["read_cdf"].return_value = dataset_with_epoch
+
+ input_example = AncillaryInput(
+ "imap_mag_l2-calibration-matrices_20251017_v001.cdf",
+ )
+
+ with pytest.raises(ValueError, match="input dataset has epoch dimension"):
+ AncillaryCombiner(input_example, "20251031")
+
+
+def test_glows_json_file_processing():
+ """Test GLOWS JSON file processing."""
+ # Create a temporary JSON file
+ json_data = {
+ "active_bad_angle_flags": [True, False, True, False],
+ "active_bad_time_flags": [True, True, False],
+ "sunrise_offset": 0.5,
+ "sunset_offset": -0.3,
+ "thresholds": {"uv_source_limit": 5.0, "excluded_region_limit": 10.0},
+ "simple_value": 42,
+ }
+
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
+ json.dump(json_data, f)
+ temp_path = f.name
+
+ try:
+ combiner = GlowsAncillaryCombiner([], "20250925")
+ dataset = combiner.convert_json_to_dataset(temp_path)
+
+ # Check that JSON data was converted properly
+ assert "active_bad_angle_flags" in dataset.data_vars
+ assert "active_bad_time_flags" in dataset.data_vars
+ assert "sunrise_offset" in dataset.data_vars
+ assert "sunset_offset" in dataset.data_vars
+ assert "thresholds_uv_source_limit" in dataset.data_vars
+ assert "thresholds_excluded_region_limit" in dataset.data_vars
+ assert "simple_value" in dataset.data_vars
+
+ # Check values
+ assert list(dataset["active_bad_angle_flags"].values) == [
+ True,
+ False,
+ True,
+ False,
+ ]
+ assert float(dataset["sunrise_offset"].values) == 0.5
+ assert float(dataset["thresholds_uv_source_limit"].values) == 5.0
+
+ finally:
+ Path(temp_path).unlink()
+
+
+def test_glows_unknown_file_type():
+ """Test error for unknown GLOWS file type."""
+ with tempfile.NamedTemporaryFile(suffix=".unknown", delete=False) as f:
+ temp_path = f.name
+
+ try:
+ combiner = GlowsAncillaryCombiner([], "20250925")
+ with pytest.raises(ValueError, match="Unknown GLOWS ancillary file type"):
+ combiner.convert_file_to_dataset(temp_path)
+ finally:
+ Path(temp_path).unlink()
+
+
+def test_convert_json_with_nested_lists():
+ """Test JSON conversion with nested lists and complex structures."""
+ json_data = {
+ "list_data": [1, 2, 3, 4],
+ "nested_dict": {"inner_list": [10, 20, 30], "inner_scalar": 99},
+ "tuple_data": (5, 6, 7),
+ }
+
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
+ json.dump(json_data, f)
+ temp_path = f.name
+
+ try:
+ combiner = AncillaryCombiner([], "20251031")
+ dataset = combiner.convert_json_to_dataset(temp_path)
+
+ # Check list handling
+ assert "list_data" in dataset.data_vars
+ assert list(dataset["list_data"].values) == [1, 2, 3, 4]
+ assert dataset["list_data"].dims == ("dim_list_data",)
+
+ # Check nested dict flattening
+ assert "nested_dict_inner_list" in dataset.data_vars
+ assert "nested_dict_inner_scalar" in dataset.data_vars
+ assert list(dataset["nested_dict_inner_list"].values) == [10, 20, 30]
+ assert dataset["nested_dict_inner_list"].dims == ("dim_nested_dict_inner_list",)
+ assert dataset["nested_dict_inner_scalar"].dims == ()
+
+ finally:
+ Path(temp_path).unlink()
+
+
+def test_glows_ancillary_combiner_with_processing_input():
+ """Test GlowsAncillaryCombiner with ProcessingInput instead of list."""
+ input_files = AncillaryInput("imap_glows_map-of-excluded-regions_20250923_v002.dat")
+
+ with patch("imap_data_access.AncillaryFilePath.construct_path") as mock_path:
+ # Create a temporary excluded regions file
+ with tempfile.NamedTemporaryFile(
+ mode="w",
+ suffix=".dat",
+ prefix="imap_glows_map-of-excluded-regions",
+ delete=False,
+ ) as f:
+ f.write("# longitude latitude\n")
+ f.write("10.0 20.0\n")
+ f.write("30.0 40.0\n")
+ temp_path = f.name
+
+ try:
+ mock_path.return_value = temp_path
+ combiner = GlowsAncillaryCombiner(input_files, "20250925")
+
+ assert len(combiner.timestamped_data) == 1
+ assert (
+ "ecliptic_longitude_deg"
+ in combiner.timestamped_data[0].dataset.data_vars
+ )
+
+ finally:
+ Path(temp_path).unlink()
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 d5d1e1913f..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_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_hi-counters-singles_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_hi-ialirt_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_hi-omni_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_hi-priority_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_hi-sectored_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_hskp_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-counters-aggregated_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-counters-singles_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-ialirt_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-nsw-angular_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-nsw-priority_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-nsw-species_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-sw-angular_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-sw-priority_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-sw-species_20241110_v999.cdf",
-]
-
-TEST_L2_FILES = [
- TEST_DATA_PATH / "imap_codice_l1a_hi-direct-events_20241110_v999.cdf",
- TEST_DATA_PATH / "imap_codice_l1a_lo-direct-events_20241110_v999.cdf",
-]
-
-# ruff: noqa
-VALIDATION_DATA = [
- 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-direct-events_20241110193900_v0.0.2.cdf",
- TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-ialirt_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-priorities_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_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-direct-events_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_lo-nsw-angular_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-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-sw-priority_20241110193900_v0.0.2.cdf",
- TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-sw-species_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 64d1366560..af9dec2bb6 100644
--- a/imap_processing/tests/codice/test_codice_l1a.py
+++ b/imap_processing/tests/codice/test_codice_l1a.py
@@ -1,442 +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, 12), # lo-sw-priority
- (77, 128, 12), # lo-nsw-priority
- (77, 128, 1), # lo-sw-species
- (77, 128, 1), # lo-nsw-species
- (77, 128, 5, 12), # lo-sw-angular
- (77, 128, 19, 12), # 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-priority
- (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
-CODICE_LO_PRODUCTS = [
- "lo-counters-aggregated",
- "lo-counters-singles",
- "lo-sw-priority",
- "lo-nsw-priority",
- "lo-sw-species",
- "lo-nsw-species",
- "lo-sw-angular",
- "lo-nsw-angular",
- "lo-ialirt",
-]
-
-
-@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]_(NumEvents|DataQuality)", 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)))
-@pytest.mark.xfail(reason="Validation test turned off; awaiting fixes")
-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 ["hskp", "hi-ialirt", "hi-omni"]:
- pytest.xfail(
- f"Awaiting implementation of proper epoch calculation for {descriptor}"
- )
-
- # TODO: Once new L1a validation is used, this probably can be tweaked for
- # even lower tolerance, and we can add checks for epoch_delta_minus
- # and epoch_delta_plus
- 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}'",
+ )
-@pytest.mark.xfail(reason="Validation test turned off; awaiting fixes")
-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}'",
+ )
-@pytest.mark.parametrize("index", range(len(DESCRIPTORS)))
-@pytest.mark.xfail(reason="Validation test turned off; awaiting fixes")
-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
- """
-
- # Hopefully I can remove this someday if Joey gives me validation data
- # with updated naming conventions
- variable_name_mapping = {
- "data_quality": "DataQuality",
- "nso_half_spin": "NSOHalfSpin",
- "rgfo_half_spin": "RGFOHalfSpin",
- "spin_period": "SpinPeriod",
- "st_bias_gain_mode": "STBiasGainMode",
- "sw_bias_gain_mode": "SWBiasGainMode",
- }
-
- 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.EnergyTable.data, decimal=3
- )
-
- # Ensure that the acquisition times are (nearly) equal
- np.testing.assert_almost_equal(
- dataset.acquisition_time_per_step.data,
- validation_dataset.AcquisitionTimePerStep.data,
- decimal=3,
- )
-
- # Ensure that the support variables derived from packet data are equal
- for variable in variable_name_mapping:
- np.testing.assert_equal(
- dataset[variable].data,
- validation_dataset[variable_name_mapping[variable]].data,
- )
+ 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}'",
+ )
- elif descriptor in CODICE_HI_PRODUCTS:
- for variable in ["spin_period", "data_quality"]:
- np.testing.assert_equal(
- dataset[variable].data,
- validation_dataset[variable_name_mapping[variable]].data,
- )
+ 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"),
+ ]
+
+ 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"
+ )
+
+
+@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."""
+
+ mock_get_file_paths.side_effect = [
+ codice_lut_path(descriptor="lo-sw-species", 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_lo-sw-species_{VALIDATION_FILE_DATE}"
+ f"_{VALIDATION_FILE_VERSION}.cdf"
+ )
+ )
+
+ 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}'",
+ )
-def test_l1a_multiple_packets():
- """Tests that an input L0 file containing multiple APIDs can be processed."""
+ 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"
+ )
- processed_datasets = process_codice_l1a(file_path=TEST_L0_FILE)
- # TODO: Could add some more checks here?
- assert len(processed_datasets) == 18
+@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 4b762672ed..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)),
- 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 50669e93ae..86e356e4d3 100644
--- a/imap_processing/tests/codice/test_codice_l2.py
+++ b/imap_processing/tests/codice/test_codice_l2.py
@@ -1,11 +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.codice.codice_l2 import process_codice_l2
-
-from .conftest import TEST_L2_FILES
+from imap_processing import imap_module_directory
+from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
+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
@@ -15,36 +41,457 @@
]
-@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.mark.parametrize(
- "test_l2_data, expected_logical_source",
- list(zip(TEST_L2_FILES, EXPECTED_LOGICAL_SOURCES)),
- 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_cdf_attrs():
+ # Create a mock ImapCdfAttributes object
+ cdf_attrs = MagicMock(spec=ImapCdfAttributes)
+ cdf_attrs.get_global_attributes.return_value = {
+ "global_attr_key": "global_attr_value"
+ }
+ cdf_attrs.get_variable_attributes.side_effect = lambda var, check_schema: {
+ "var1": {"attr1": "value1"},
+ "test-product-var2": {"attr2": "value2"},
+ }[var]
+ return cdf_attrs
+
+
+@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)
+
+ # 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)
+
+
+def test_get_geometric_factor_lut(processing_dependencies, mock_get_file_paths):
+ gfactor_lut = get_geometric_factor_lut(processing_dependencies)
+
+ # 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)),
+ )
+
+ 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(
+ {
+ "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),
+ }
+ )
+
+ 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"
+ )
+ )
+
+ l2_val_data = load_cdf(l2_val_data)
+
+ 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)
+
+
+@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]
+
+ 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"),
+ ]
- dataset = test_l2_data
+ 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}'",
+ )
- assert dataset.attrs["Logical_source"] == expected_logical_source
+ 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 8439b5c2eb..9bae21b7b3 100644
--- a/imap_processing/tests/conftest.py
+++ b/imap_processing/tests/conftest.py
@@ -1,12 +1,9 @@
"""Global pytest configuration for the package."""
import logging
-import os
-import re
import time
from contextlib import contextmanager
from pathlib import Path
-from typing import Optional, Union
import cdflib
import imap_data_access
@@ -44,18 +41,11 @@ def clear_spin_and_repoint_paths(monkeypatch):
monkeypatch.setattr(spice_config, "_repoint_table_path", None)
-# Furnishing fixtures for testing kernels
-# ---------------------------------------
-@pytest.fixture(autouse=True)
-def _autoclear_spice():
- """Automatically clears out all SPICE remnants after every single test to
- prevent the kernel pool from interfering with future tests. Option autouse
- ensures this is run after every test."""
- yield
- spiceypy.kclear()
+@pytest.fixture(scope="session")
+def _download_kernels(spice_test_data_path):
+ _download_external_kernels(spice_test_data_path)
-@pytest.fixture(scope="session")
def _download_external_kernels(spice_test_data_path):
"""This fixture downloads externally-located kernels into the tests/spice/test_data
directory if they do not already exist there. The fixture is not intended to be
@@ -65,8 +55,7 @@ def _download_external_kernels(spice_test_data_path):
kernel_urls = [
"https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de440s.bsp",
"https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/pck00011.tpc",
- "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/"
- "earth_1962_240827_2124_combined.bpc",
+ "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/earth_latest_high_prec.bpc",
]
for kernel_url in kernel_urls:
@@ -107,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
@@ -135,7 +124,10 @@ def _download_external_data():
file.write(response.content)
logger.info(f"Downloaded file: {source}")
else:
- logger.error(f"Failed to download file: {response.status_code}")
+ logger.error(
+ f"Failed to download file: {source} "
+ f"with response: {response.status_code}"
+ )
else:
logger.info(f"File already exists: {destination}")
@@ -149,9 +141,8 @@ def pytest_collection_modifyitems(items):
+---------------------+----------------------------+
| pytest mark | fixture added |
+=====================+============================+
- | external_kernel | _download_external_kernels |
+ | external_kernel | _download_kernels |
| external_test_data | _download_test_data |
- | use_test_metakernel | use_test_metakernel |
+---------------------+----------------------------+
Notes
@@ -162,9 +153,8 @@ def pytest_collection_modifyitems(items):
pytest.hookspec.pytest_collection_modifyitems
"""
markers_to_fixtures = {
- "external_kernel": "_download_external_kernels",
+ "external_kernel": "_download_kernels",
"external_test_data": "_download_test_data",
- "use_test_metakernel": "use_test_metakernel",
}
for item in items:
@@ -178,7 +168,7 @@ def spice_test_data_path(imap_tests_path):
return imap_tests_path / "spice/test_data"
-@pytest.fixture
+@pytest.fixture(autouse=True, scope="session")
def furnish_time_kernels(spice_test_data_path):
"""Furnishes (temporarily) the testing LSK and SCLK"""
spiceypy.kclear()
@@ -191,17 +181,23 @@ def furnish_time_kernels(spice_test_data_path):
@pytest.fixture
-def furnish_sclk(spice_test_data_path):
- """Furnishes (temporarily) the SCLK for JPSS stored in the package data directory"""
- test_sclk = spice_test_data_path / "imap_sclk_0000.tsc"
- spiceypy.furnsh(str(test_sclk))
- yield test_sclk
- spiceypy.kclear()
+def furnish_kernels(spice_test_data_path):
+ """
+ Return a function to use as a context manager to furnish a list of kernels.
+ Kernel files are assumed to exist in the tests/spice/test_data directory.
-@pytest.fixture
-def furnish_kernels(spice_test_data_path):
- """Return a function that will furnish an arbitrary list of kernels."""
+ Examples
+ --------
+ >>> def test_spicey_function(furnish_kernels):
+ >>> kernels_to_furnish = [
+ >>> "naif0012.tls",
+ >>> "kernel_0.tm",
+ >>> "kernel_1.bsp",
+ >>> ]
+ >>> with furnish_kernels(kernels_to_furnish):
+ >>> result = spicey_function()
+ """
@contextmanager
def furnish_kernels(kernels: list[Path]):
@@ -213,149 +209,6 @@ def furnish_kernels(kernels: list[Path]):
return furnish_kernels
-@pytest.fixture(scope="session")
-def monkeypatch_session():
- m = pytest.MonkeyPatch()
- yield m
- m.undo()
-
-
-def make_metakernel_from_kernels(metakernel, kernels):
- """Helper function that writes a test metakernel from a list of filenames"""
- with open(metakernel, "w") as mk:
- mk.writelines(
- [
- "\n",
- "\\begintext\n",
- "\n",
- "This is a temporary metakernel for imap_processing"
- " unit and integration testing.\n",
- "\n",
- "\\begindata\n",
- "\n",
- "KERNELS_TO_LOAD = (\n",
- ]
- )
- # Put single quotes around every kernel name
- kernels_with_quotes = [" '" + kern + "'" for kern in kernels]
- # Add a comma and EOL to the end of each kernel path except the last.
- formatted_kernels = [kern + ",\n" for kern in kernels_with_quotes[0:-1]]
- # Add ')' to the last kernel
- formatted_kernels.append(kernels_with_quotes[-1] + "\n)\n\n")
- mk.writelines(formatted_kernels)
-
-
-def get_test_kernels_to_load(template_path, kernel_dir_path):
- """
- Helper function for grabbing a list of kernel filenames from the test
- metakernel template. This is necessary in order to get absolute paths on
- any system. Formats the absolute paths using the test data path fixture
- value.
- """
- kernels_to_load = []
- max_line_length = 80
- with open(template_path) as mk:
- for k in mk:
- kernel = k.rstrip("\n").format(
- **{"SPICE_TEST_DATA_PATH": str(kernel_dir_path.absolute())}
- )
- while len(kernel) > 0:
- if len(kernel) <= max_line_length:
- kernels_to_load.append(kernel)
- break
- else:
- slash_positions = np.array(
- [m.start() for m in re.finditer("/", kernel)]
- )
- stop_idx = (
- slash_positions[slash_positions < max_line_length - 1].max() + 1
- )
- kernels_to_load.append(kernel[0:stop_idx] + "+")
- kernel = kernel[stop_idx:]
- return kernels_to_load
-
-
-@pytest.fixture(scope="session", autouse=True)
-def session_test_metakernel(monkeypatch_session, tmpdir_factory, spice_test_data_path):
- """Generate a metakernel from the template metakernel by injecting the local
- path into the metakernel and set the SPICE_METAKERNEL environment variable.
-
- Notes
- -----
- - This fixture needs to `scope=session` so that the SPICE_METAKERNEL
- environment variable is available for other fixtures that require time
- conversions using spiceypy.
- - No furnishing of kernels occur as part of this fixture. This allows other
- fixtures with lesser scope or individual tests to override the environment
- variable as needed. Use the `metakernel_path_not_set` fixture in tests that
- need to override the environment variable.
- """
- template_path = spice_test_data_path / "imap_simple_metakernel.template"
- kernels_to_load = get_test_kernels_to_load(template_path, spice_test_data_path)
- metakernel_path = tmpdir_factory.mktemp("spice") / "imap_2024_v001.tm"
- make_metakernel_from_kernels(metakernel_path, kernels_to_load)
- monkeypatch_session.setenv("SPICE_METAKERNEL", str(metakernel_path))
- yield str(metakernel_path)
- spiceypy.kclear()
-
-
-@pytest.fixture
-def use_test_metakernel(
- request, monkeypatch, spice_test_data_path, session_test_metakernel
-):
- """
- Generate a metakernel and set SPICE_METAKERNEL environment variable.
-
- This fixture generates a metakernel in the directory pointed to by
- `imap_data_access.config["DATA_DIR"]` and sets the SPICE_METAKERNEL
- environment variable to point to it for use by the `@ensure_spice` decorator.
- The default metekernel is named "imap_simple_metakernel.template". Other
- metakerels can be specified by marking the test with metakernel. See
- examples below.
-
- Parameters
- ----------
- request : fixture
- monkeypatch : fixture
- spice_test_data_path : fixture
- session_test_metakernel : fixture
-
- Yields
- ------
- metakernel_path : Path
-
- Examples
- --------
- 1. Use the default metakernel template
- >>> def test_my_spicey_func(use_test_metakernel):
- ... pass
-
- 2. Specify a different metakernel template
- >>> @pytest.mark.use_test_metakernel("other_template_mk.template")
- ... def test_my_spicey_func():
- ... pass
- """
- marker = request.node.get_closest_marker("use_test_metakernel")
- if marker is None:
- yield session_test_metakernel
- else:
- template_name = marker.args[0]
- template_path = spice_test_data_path / template_name
- metakernel_path = imap_data_access.config["DATA_DIR"] / "imap_2024_v001.tm"
- kernels_to_load = get_test_kernels_to_load(template_path, spice_test_data_path)
- make_metakernel_from_kernels(metakernel_path, kernels_to_load)
- monkeypatch.setenv("SPICE_METAKERNEL", str(metakernel_path))
- yield str(metakernel_path)
- spiceypy.kclear()
-
-
-@pytest.fixture
-def _unset_metakernel_path(monkeypatch):
- """Temporarily unsets the SPICE_METAKERNEL environment variable"""
- if os.getenv("SPICE_METAKERNEL", None) is not None:
- monkeypatch.delenv("SPICE_METAKERNEL")
-
-
@pytest.fixture
def use_test_spin_data_csv(monkeypatch):
"""Monkeypatches `spin._spin_table_paths` to the input Path."""
@@ -368,7 +221,11 @@ def wrapped_set_spin_data_filepath(paths: list[Path]):
@pytest.fixture
def use_fake_spin_data_for_time(
- request, use_test_spin_data_csv, tmp_path, generate_spin_data, spin_period=15.0
+ request,
+ use_test_spin_data_csv,
+ tmp_path,
+ generate_spin_data,
+ spin_period=15.0,
):
"""
Generate and use fake spin data for testing.
@@ -384,8 +241,8 @@ def use_fake_spin_data_for_time(
def wrapped_set_spin_data_filepath(
start_met: float,
- end_met: Optional[int] = None,
- spin_period: Optional[float] = 15.0,
+ end_met: int | None = None,
+ spin_period: float | None = 15.0,
) -> pd.DataFrame:
"""
Generate and use fake spin data for testing.
@@ -413,8 +270,8 @@ def wrapped_set_spin_data_filepath(
def generate_spin_data():
def make_data(
start_met: float,
- end_met: Optional[float] = None,
- spin_period: Optional[float] = None,
+ end_met: float | None = None,
+ spin_period: float | None = None,
) -> pd.DataFrame:
"""
Generate a spin table CSV covering one or more days.
@@ -516,9 +373,9 @@ def wrapped_set_repoint_data_filepath(path: Path):
def generate_repoint_data(
- repoint_start_met: Union[float, np.ndarray],
- repoint_end_met: Optional[Union[float, np.ndarray]] = None,
- repoint_id_start: Optional[int] = 0,
+ repoint_start_met: float | np.ndarray,
+ repoint_end_met: float | np.ndarray | None = None,
+ repoint_id_start: int | None = 0,
) -> pd.DataFrame:
"""
Generate a repoint dataframe for the star/end times provided.
@@ -540,9 +397,10 @@ def generate_repoint_data(
Repoint dataframe with start and end repoint times provided and incrementing
repoint_ids starting at 1.
"""
- repoint_start_times = np.array(repoint_start_met)
+ repoint_start_times = np.atleast_1d(repoint_start_met)
if repoint_end_met is None:
repoint_end_met = repoint_start_times + 15 * 60
+
# Calculate UTC times without spice (accepting ~5 second inaccuracy)
repoint_start_dt64 = TTJ2000_EPOCH + (repoint_start_times * 1e9).astype(
"timedelta64[ns]"
@@ -580,9 +438,9 @@ def use_fake_repoint_data_for_time(use_test_repoint_data_csv, tmp_path):
"""
def wrapped_repoint_data_filepath(
- repoint_start_met: Union[float, np.ndarray],
- repoint_end_met: Optional[Union[float, np.ndarray]] = None,
- repoint_id_start: Optional[int] = 0,
+ repoint_start_met: float | np.ndarray,
+ repoint_end_met: float | np.ndarray | None = None,
+ repoint_id_start: int | None = 0,
) -> pd.DataFrame:
"""
Generate and use fake repoint data for testing.
@@ -609,6 +467,36 @@ def wrapped_repoint_data_filepath(
return wrapped_repoint_data_filepath
+@pytest.fixture
+def imap_ena_sim_metakernel(furnish_kernels, _download_kernels):
+ kernels = [
+ "imap_sclk_0000.tsc",
+ "naif0012.tls",
+ "imap_spk_demo.bsp",
+ "sim_1yr_imap_attitude.bc",
+ "imap_130.tf",
+ "de440s.bsp",
+ "imap_science_120.tf",
+ "sim_1yr_imap_pointing_frame.bc",
+ ]
+ with furnish_kernels(kernels) as k:
+ yield k
+
+
+@pytest.fixture
+def imap_ialirt_sim_metakernel(furnish_kernels):
+ kernels = ["imap_130.tf"]
+ with furnish_kernels(kernels) as k:
+ yield k
+
+
+@pytest.fixture
+def imap_simple_sim_metakernel(furnish_kernels):
+ kernels = ["imap_sclk_0000.tsc", "naif0012.tls", "imap_spk_demo.bsp"]
+ with furnish_kernels(kernels) as k:
+ yield k
+
+
# Shared with i-alirt and mag tests
@pytest.fixture
def mag_test_l1b_calibration_data():
@@ -633,3 +521,4 @@ def mag_test_l1b_calibration_data():
# This is to enable downloading files easier by letting us
# run this file directly
_download_external_data()
+ _download_external_kernels(imap_module_directory / "tests" / "spice" / "test_data")
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 dec9e519d1..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,25 +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)
+ 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 from_cdf method."""
+ """Test coverage for instantiating HiPointingSet from cdf."""
hi_pset = ena_maps.HiPointingSet(hi_pset_cdf_path)
assert isinstance(hi_pset, ena_maps.HiPointingSet)
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)
+ 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
@@ -173,40 +214,69 @@ def test_plays_nice_with_rectangular_sky_map(self, hi_pset_cdf_path):
@pytest.fixture
def lo_pset_ds():
- h_counts = np.zeros((1, 3600, 40, 7))
+ h_counts = np.zeros((1, 7, 3600, 40))
h_counts[:, :, 0:10, :] = 1
- exposure_time = np.full((1, 3600, 40, 7), 0.5)
+ exposure_time = np.full((1, 7, 3600, 40), 0.5)
+ lons = np.linspace(0, 359.9, 3600)
+ lats = np.linspace(-2, 2, 40)
+ lons, lats = np.meshgrid(lons, lats, indexing="ij")
+ hae_longitude = np.empty((1, 3600, 40))
+ hae_latitude = np.empty((1, 3600, 40))
+ hae_longitude[0, :, :] = lons
+ hae_latitude[0, :, :] = lats
+
dataset = xr.Dataset()
dataset["h_counts"] = xr.DataArray(
h_counts,
- dims=("epoch", "longitude", "latitude", "energy"),
+ dims=("epoch", "esa_energy_step", "spin_angle", "off_angle"),
name="h_counts",
)
dataset["exposure_time"] = xr.DataArray(
exposure_time,
- dims=("epoch", "longitude", "latitude", "energy"),
+ dims=("epoch", "esa_energy_step", "spin_angle", "off_angle"),
name="exposure_time",
)
+ dataset["hae_longitude"] = xr.DataArray(
+ hae_longitude,
+ dims=("epoch", "spin_angle", "off_angle"),
+ name="exposure_time",
+ )
+ dataset["hae_latitude"] = xr.DataArray(
+ hae_latitude,
+ dims=("epoch", "spin_angle", "off_angle"),
+ name="exposure_time",
+ )
+
dataset.coords["epoch"] = xr.DataArray(
[8.1794907049e17],
dims=["epoch"],
name="epoch",
)
- dataset.coords["longitude"] = xr.DataArray(
+ 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=["longitude"],
- name="longitude",
+ dims=["spin_angle"],
+ name="spin_angle",
)
- dataset.coords["latitude"] = xr.DataArray(
+ dataset.coords["off_angle"] = xr.DataArray(
[i for i in range(40)],
- dims=["latitude"],
- name="latitude",
+ dims=["off_angle"],
+ name="off_angle",
)
- dataset.coords["energy"] = xr.DataArray(
+ dataset.coords["esa_energy_step"] = xr.DataArray(
[i for i in range(1, 8)],
- dims=["energy"],
- name="energy",
+ dims=["esa_energy_step"],
+ name="esa_energy_step",
)
attr_mgr = ImapCdfAttributes()
@@ -222,7 +292,7 @@ def lo_pset_cdf_path(imap_tests_path):
@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
+@pytest.mark.usefixtures("imap_ena_sim_metakernel")
class TestLoPointingSet:
"""Test suite for LoPointingSet class."""
@@ -230,10 +300,19 @@ def test_init(self, lo_pset_ds):
"""Test coverage for __init__ method."""
lo_pset = ena_maps.LoPointingSet(lo_pset_ds)
assert isinstance(lo_pset, ena_maps.LoPointingSet)
- assert lo_pset.spice_reference_frame == geometry.SpiceFrame.IMAP_DPS
+ assert lo_pset.spice_reference_frame == geometry.SpiceFrame.IMAP_HAE
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
@@ -249,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):
@@ -437,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,
@@ -445,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(
@@ -576,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")
@@ -594,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
@@ -621,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="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="Attributes for variable no_attrs_var not found"
+ 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)
@@ -934,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 = []
@@ -961,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(
[
@@ -972,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()
@@ -998,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"
)
@@ -1159,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
@@ -1210,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 fc5c379fa5..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):
- 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):
- 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 bd822c5ad8..0c5d03ffbb 100644
--- a/imap_processing/tests/ena_maps/test_naming.py
+++ b/imap_processing/tests/ena_maps/test_naming.py
@@ -166,10 +166,14 @@ def test_get_map_frame(
self,
):
# Test with a string frame
- assert MapDescriptor.get_map_coord_frame("hae") is SpiceFrame.ECLIPJ2000
+ assert MapDescriptor.get_map_coord_frame("hae") is SpiceFrame.IMAP_HAE
+ 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):
@@ -180,7 +184,7 @@ def test_get_output_map_structure_from_descriptor_string(self):
assert isinstance(output_map_structure_half_deg, RectangularSkyMap)
assert output_map_structure_half_deg.spacing_deg == 0.5
assert (
- output_map_structure_half_deg.spice_reference_frame is SpiceFrame.ECLIPJ2000
+ output_map_structure_half_deg.spice_reference_frame is SpiceFrame.IMAP_HAE
)
descriptor_str_nside32 = "ulc-ena-h-sf-nsp-full-hae-nside32-1yr"
@@ -217,7 +221,7 @@ def test_init_and_instrument_descriptor_hi45(self):
assert md_h45.instrument_descriptor == "h45"
assert md_h45.duration == "2mo"
assert md_h45.coordinate_system == "hae"
- assert md_h45.map_spice_coord_frame == SpiceFrame.ECLIPJ2000
+ assert md_h45.map_spice_coord_frame == SpiceFrame.IMAP_HAE
def test_init_and_instrument_descriptor_lo_hi_throughput_075(self):
md_lo_hi_075 = MapDescriptor(
@@ -236,7 +240,7 @@ def test_init_and_instrument_descriptor_lo_hi_throughput_075(self):
assert md_lo_hi_075.instrument_descriptor == "t075"
assert md_lo_hi_075.duration == "6mo"
assert md_lo_hi_075.coordinate_system == "hae"
- assert md_lo_hi_075.map_spice_coord_frame == SpiceFrame.ECLIPJ2000
+ assert md_lo_hi_075.map_spice_coord_frame == SpiceFrame.IMAP_HAE
def test_from_string(
self,
@@ -301,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/ena_maps/test_spatial_utils.py b/imap_processing/tests/ena_maps/test_spatial_utils.py
index ea93e15ddd..19a70bf50e 100644
--- a/imap_processing/tests/ena_maps/test_spatial_utils.py
+++ b/imap_processing/tests/ena_maps/test_spatial_utils.py
@@ -69,7 +69,8 @@ def test_build_solid_angle_map_equal_at_equal_el(spacing):
@pytest.mark.parametrize(
- "spacing, match_str", zip(invalid_spacings, invalid_spacings_match_str)
+ "spacing, match_str",
+ zip(invalid_spacings, invalid_spacings_match_str, strict=False),
)
def test_build_solid_angle_map_invalid_spacing(spacing, match_str):
"""Test build_solid_angle_map function raises error for invalid spacing."""
diff --git a/imap_processing/tests/external_test_data_config.py b/imap_processing/tests/external_test_data_config.py
index 96910a8e1e..b7c7ba4bf4 100644
--- a/imap_processing/tests/external_test_data_config.py
+++ b/imap_processing/tests/external_test_data_config.py
@@ -7,63 +7,149 @@
"""
# 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_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_hi-counters-singles_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_hi-ialirt_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_hi-omni_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_hi-direct-events_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_hi-priority_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_hi-sectored_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_hskp_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-counters-aggregated_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-counters-singles_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-ialirt_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-nsw-angular_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-nsw-priority_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-nsw-species_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-direct-events_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-sw-angular_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-sw-priority_20241110_v999.cdf", "codice/data/"),
- ("imap_codice_l1a_lo-sw-species_20241110_v999.cdf", "codice/data/"),
-
- ("imap_codice_l1a_hi-counters-aggregated_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-counters-singles_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_hi-counters-singles_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-ialirt_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_hi-ialirt_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-nsw-angular_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_hi-omni_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-nsw-priority_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_hi-direct-events_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-nsw-species_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_hi-priorities_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-direct-events_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_hi-sectored_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-sw-angular_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_hskp_20241110193622_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-sw-priority_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-counters-aggregated_20241110193700_v0.0.0.cdf", "codice/data/validation/"),
- ("imap_codice_l1a_lo-sw-species_20241110193700_v0.0.0.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/"),
("imap_hi_l1b_45sensor-de_20250415_v999.cdf", "hi/data/l1/"),
+ ("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-Ultra45_r1_L1_V0_shortened.csv", "ultra/data/l1/"),
+ ("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_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",
@@ -78,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/"),
@@ -90,7 +181,6 @@
("imap_ultra_l1b-sensor-gf-noblades_20250101_v000.csv", "ultra/data/l1/"),
("imap_ultra_l1b-45sensor-leftslit-lookup_20250101_v000.csv", "ultra/data/l1/"),
("imap_ultra_l1b-45sensor-rightslit-lookup_20250101_v000.csv", "ultra/data/l1/"),
- ("imap_ultra_l1b-45sensor-imgparams-lookup_20250101_v000.csv", "ultra/data/l1/"),
("imap_ultra_l1b-45sensor-tdc-norm-lookup_20250101_v000.csv", "ultra/data/l1/"),
("imap_ultra_l1b-45sensor-back-pos-lookup_20250101_v000.csv", "ultra/data/l1/"),
("imap_ultra_l1b-egynorm-lookup_20250101_v000.csv", "ultra/data/l1/"),
@@ -99,8 +189,28 @@
("imap_ultra_l1b-45sensor-spbtphcorr_20250101_v000.csv", "ultra/data/l1/"),
("imap_ultra_l1b-90sensor-sptpphcorr_20250101_v000.csv", "ultra/data/l1/"),
("imap_ultra_l1b-90sensor-spbtphcorr_20250101_v000.csv", "ultra/data/l1/"),
+ ("imap_ultra_l1b-90sensor-scattering-calibration-data_20250101_v000.csv", "ultra/data/l1/"),
("ultra45_raw_sc_ultrarawimg_withFSWccs_FM45_40P_Phi28p5_BeamCal_LinearScan_"
"phi2850_theta-000_20240207T102740_revised20250724.csv", "ultra/data/l1/"),
+ ("imap_ultra_l1b-45sensor-tofxeflat_20250101_v000.pgm", "ultra/data/l1/"),
+ ("imap_ultra_l1b-45sensor-tofxemedium_20250101_v000.pgm", "ultra/data/l1/"),
+ ("imap_ultra_l1b-45sensor-tofxesteep_20250101_v000.pgm", "ultra/data/l1/"),
+ ("imap_ultra_l1b-90sensor-tofxeflat_20250101_v000.pgm", "ultra/data/l1/"),
+ ("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-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",
@@ -151,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 6eebe14721..7f34dc6dc1 100644
--- a/imap_processing/tests/glows/conftest.py
+++ b/imap_processing/tests/glows/conftest.py
@@ -1,12 +1,19 @@
from pathlib import Path
+import numpy as np
import pytest
+import xarray as xr
from imap_processing.glows.l0 import decom_glows
from imap_processing.glows.l1a.glows_l1a import glows_l1a, process_de_l0
from imap_processing.glows.l1a.glows_l1a_data import HistogramL1A
from imap_processing.glows.l1b.glows_l1b import glows_l1b
+from imap_processing.glows.l1b.glows_l1b_data import (
+ AncillaryExclusions,
+ AncillaryParameters,
+)
from imap_processing.glows.l2.glows_l2 import glows_l2
+from imap_processing.glows.l2.glows_l2_data import DailyLightcurve
@pytest.fixture
@@ -15,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"""
@@ -23,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 = []
@@ -41,10 +76,300 @@ def l1a_dataset(packet_path):
@pytest.fixture
-def l1b_hist_dataset(l1a_dataset):
- return glows_l1b(l1a_dataset[0])
+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_hist_dataset, mock_pipeline_settings):
+ return glows_l2(l1b_hist_dataset, mock_pipeline_settings)
+
+
+@pytest.fixture
+def mock_ancillary_exclusions():
+ """Create a mock AncillaryExclusions object for testing."""
+ # Create mock datasets with epoch dimension that can be used with limit_by_day()
+ # Use a range of dates that covers the expected test data dates
+ epoch_range = np.arange(
+ np.datetime64("2010-01-01"), np.datetime64("2010-12-31"), dtype="datetime64[D]"
+ )
+
+ # Create datasets with epoch dimension and some mock data
+ mock_excluded_regions = xr.Dataset(
+ {
+ # degrees in [0, 360)
+ "ecliptic_longitude_deg": (
+ ["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", "source"],
+ np.tile(
+ np.array([18.4119, 0.0, 35.0], dtype=np.float64),
+ (len(epoch_range), 1),
+ ),
+ ),
+ },
+ coords={"epoch": epoch_range},
+ )
+
+ mock_uv_sources = xr.Dataset(
+ {
+ "object_name": (
+ ["epoch", "source"],
+ [["star1", "star2", "star3"]] * len(epoch_range),
+ ),
+ # degrees in [0, 360)
+ "ecliptic_longitude_deg": (
+ ["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", "source"],
+ 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.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"],
+ [["2026-01-01T15:00:00", "2026-01-01T15:01:00"]] * len(epoch_range),
+ ),
+ "histogram_mask_array": (
+ ["epoch", "time_block"],
+ [["0" * 3600, "0" * 600 + "1" * 100 + "0" * 2900]] * len(epoch_range),
+ ),
+ },
+ coords={"epoch": epoch_range},
+ )
+
+ mock_exclusions_by_instr_team = xr.Dataset(
+ {
+ "l1b_unique_block_identifier": (
+ ["epoch", "time_block"],
+ [["2026-01-01T15:00:00", "2026-01-01T15:01:00"]] * len(epoch_range),
+ ),
+ "histogram_mask_array": (
+ ["epoch", "time_block"],
+ [["0" * 100 + "1" * 10 + "0" * 3490, "0" * 3600]] * len(epoch_range),
+ ),
+ },
+ coords={"epoch": epoch_range},
+ )
+
+ return AncillaryExclusions(
+ excluded_regions=mock_excluded_regions,
+ uv_sources=mock_uv_sources,
+ suspected_transients=mock_suspected_transients,
+ exclusions_by_instr_team=mock_exclusions_by_instr_team,
+ )
+
+
+@pytest.fixture
+def mock_ancillary_parameters(mock_conversion_table_dict):
+ """Create a mock AncillaryParameters object for testing."""
+
+ 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,
+ "max": 80.0,
+ "n_bits": 8,
+ "p01": 0.0,
+ "p02": 0.0,
+ "p03": 0.0,
+ "p04": 0.0,
+ "physical_unit": "Celsius degree",
+ },
+ "hv_voltage": {
+ "min": 0.0,
+ "max": 3500.0,
+ "n_bits": 12,
+ "p01": 0.0,
+ "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",
+ },
+ "pulse_length": {
+ "min": 0.0,
+ "max": 255.0,
+ "n_bits": 8,
+ "p01": 0.0,
+ "p02": 0.0,
+ "p03": 0.0,
+ "p04": 0.0,
+ "physical_unit": "Celsius degree",
+ },
+ }
+
+ 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 l2_hist_dataset(l1b_datasets):
- return glows_l2(l1b_datasets)
+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):
+ self.spin_period_ground_average = np.float64(0.0)
+ self.spin_period_ground_std_dev = np.float64(0.0)
+ self.position_angle_offset_average = np.float64(0.0)
+ self.position_angle_offset_std_dev = np.float64(0.0)
+ self.spin_axis_orientation_average = np.zeros(2, dtype=np.float64)
+ self.spin_axis_orientation_std_dev = np.zeros(2, dtype=np.float64)
+ self.spacecraft_location_average = np.zeros(3, dtype=np.float64)
+ self.spacecraft_location_std_dev = np.zeros(3, dtype=np.float64)
+ self.spacecraft_velocity_average = np.zeros(3, dtype=np.float64)
+ self.spacecraft_velocity_std_dev = np.zeros(3, dtype=np.float64)
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 524fcdfb79..c13c9e9ac8 100644
--- a/imap_processing/tests/glows/test_glows_l1b.py
+++ b/imap_processing/tests/glows/test_glows_l1b.py
@@ -1,5 +1,6 @@
import dataclasses
from pathlib import Path
+from unittest.mock import patch
import numpy as np
import pytest
@@ -7,25 +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,)),
@@ -35,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(
@@ -67,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
@@ -139,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})
@@ -185,29 +199,44 @@ def ancillary_dict():
return dictionary
-def test_histogram_mapping():
- time_val = 1111111.11
- # A = 2.318
- # B = 69.5454
+@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_flag_uv_and_excluded,
+ mock_ancillary_exclusions,
+ mock_ancillary_parameters,
+ mock_pipeline_settings,
+):
+ mock_spice_function.side_effect = mock_update_spice_parameters
+ time_val = np.double(1111111.11)
+
+ test_hists = np.zeros(3600)
expected_temp = 100
-
- test_hists = np.zeros((200, 3600))
- # For temp
- encoded_val = expected_temp * 2.318 + 69.5454
+ 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,
@@ -221,57 +250,174 @@ def test_histogram_mapping():
time_val,
time_val,
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
-def test_process_histogram(hist_dataset):
- time_val = np.single(1111111.11)
- # A = 2.318
- # B = 69.5454
+@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.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,
+ 64, # flags_set_onboard: bit 6 (is_night) set
+ 1, # is_generated_on_ground
0,
+ 3600,
0,
- 0,
- 0,
- encoded_val,
- encoded_val,
- encoded_val,
- encoded_val,
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,
+ 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)
+ output = process_histogram(
+ 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
+
+
+@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):
- output = process_de(de_dataset)
+
+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))
@@ -288,19 +434,39 @@ def test_process_de(de_dataset, ancillary_dict):
assert np.isclose(output[8].data[0], expected_temp)
-def test_glows_l1b(de_dataset, hist_dataset):
- hist_output = glows_l1b(hist_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_glows_l1b(
+ 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
+
+ hist_output = glows_l1b(
+ hist_dataset,
+ 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,
+ )
assert hist_output["histogram"].dims == ("epoch", "bins")
assert hist_output["histogram"].shape == (20, 3600)
# 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",
]
@@ -337,11 +503,17 @@ def test_glows_l1b(de_dataset, hist_dataset):
"spacecraft_velocity_std_dev",
"flags",
]
-
for key in expected_hist_data:
assert key in hist_output
- de_output = glows_l1b(de_dataset)
+ 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 = [
@@ -363,16 +535,178 @@ def test_glows_l1b(de_dataset, hist_dataset):
assert key in de_output
-def test_generate_histogram_dataset(hist_dataset):
- l1b_data = glows_l1b(hist_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_generate_histogram_dataset(
+ 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
+
+ l1b_data = glows_l1b(
+ hist_dataset,
+ 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,
+ )
+
output_path = write_cdf(l1b_data)
assert Path.exists(output_path)
-def test_generate_de_dataset(de_dataset):
- l1b_data = glows_l1b(de_dataset)
+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)
assert Path.exists(output_path)
+
+
+@pytest.mark.external_kernel
+@pytest.mark.usefixtures("use_fake_spin_data_for_time")
+@patch("imap_processing.spice.geometry.imap_state")
+def test_hist_spice_output(
+ mock_imap_state,
+ use_fake_spin_data_for_time,
+ furnish_kernels,
+ mock_ancillary_exclusions,
+ mock_ancillary_parameters,
+ mock_pipeline_settings,
+):
+ # 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
+ [4.0, 5.0, 6.0, 0.4, 0.5, 0.6],
+ ]
+ )
+
+ # Generate a fake spin data for time
+ data_start_time = 504975600.125 # 2026-01-01T15:00:00.125
+ use_fake_spin_data_for_time(data_start_time)
+ params = {
+ "histogram": np.zeros(3600),
+ "seq_count_in_pkts_file": 0,
+ "first_spin_id": 0,
+ "last_spin_id": 0,
+ "flags_set_onboard": 0,
+ "is_generated_on_ground": 1,
+ "number_of_spins_per_block": 1,
+ "number_of_bins_per_histogram": 3600,
+ "number_of_events": 0,
+ "filter_temperature_average": 20.0,
+ "filter_temperature_variance": 0.0,
+ "hv_voltage_average": 1000.0,
+ "hv_voltage_variance": 0.0,
+ "spin_period_average": 10.0,
+ "spin_period_variance": 0.0,
+ "pulse_length_average": 50.0,
+ "pulse_length_variance": 0.0,
+ "imap_start_time": 504975603.125,
+ "imap_time_offset": 200.0,
+ "glows_start_time": 504975603.125,
+ "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_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)
+ assert isinstance(hist_data.position_angle_offset_average, np.float64)
+ assert isinstance(hist_data.position_angle_offset_std_dev, np.float64)
+ assert hist_data.spin_axis_orientation_std_dev.shape == (2,)
+ assert hist_data.spin_axis_orientation_average.shape == (2,)
+ assert hist_data.spacecraft_location_average.shape == (3,)
+ 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 c6d5cd0388..bc298c4680 100644
--- a/imap_processing/tests/glows/test_glows_l1b_data.py
+++ b/imap_processing/tests/glows/test_glows_l1b_data.py
@@ -1,16 +1,21 @@
import json
from pathlib import Path
+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
def test_glows_l1b_ancillary_file():
@@ -79,9 +84,38 @@ def test_glows_l1b_de():
assert np.allclose(pulse_len, expected_pulse)
-def test_validation_data_histogram(l1a_dataset):
- l1b = [glows_l1b(l1a_dataset[0]), glows_l1b(l1a_dataset[1])]
- end_time = l1b[0]["epoch"].data[-1]
+@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,
+ 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
+ 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
@@ -97,7 +131,6 @@ def test_validation_data_histogram(l1a_dataset):
"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",
@@ -125,11 +158,15 @@ def test_validation_data_histogram(l1a_dataset):
}
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"],
@@ -146,10 +183,15 @@ def test_validation_data_histogram(l1a_dataset):
)
-def test_validation_data_de(l1a_dataset):
+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)
+ l1b = glows_l1b_de(de_data, mock_conversion_table_dict)
validation_data = (
Path(__file__).parent / "validation_data" / "imap_glows_l1b_de_output.json"
)
@@ -197,3 +239,199 @@ def test_validation_data_de(l1a_dataset):
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 ffea68b281..b4e40de25f 100644
--- a/imap_processing/tests/glows/test_glows_l2.py
+++ b/imap_processing/tests/glows/test_glows_l2.py
@@ -1,13 +1,22 @@
+from unittest.mock import patch
+
import numpy as np
import pytest
import xarray as xr
-from imap_processing.glows.l2.glows_l2 import (
- generate_l2,
- glows_l2,
- return_good_times,
+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,
+ 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
@pytest.fixture
@@ -17,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
@@ -28,62 +37,149 @@ def l1b_hists():
return input
-def test_glows_l2(l1b_hist_dataset):
- l2 = glows_l2(l1b_hist_dataset)[0]
- assert l2.attrs["Logical_source"] == "imap_glows_l2_hist"
+@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,
+ 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(
+ 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,
+ )
+ 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)
-
-
-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)
-
-
-def test_generate_l2(l1b_hist_dataset):
- 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 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
)
- assert np.isclose(
- l2.hv_voltage_average, expected_values["hv_voltage_average"], 0.01
+ caplog.set_level("WARNING")
+ result = glows_l2(
+ l1b_hist_dataset_no_good_times, mock_pipeline_settings, mock_calibration_dataset
)
- assert np.isclose(
- l2.hv_voltage_std_dev, expected_values["hv_voltage_std_dev"], 0.01
+ 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_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)
+@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,
+ 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(
+ 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,
+ )
+ 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.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/l0/imap_hi_l0_raw-memdmp_20260926_v003.pkts b/imap_processing/tests/hi/data/l0/imap_hi_l0_raw-memdmp_20260926_v003.pkts
new file mode 100644
index 0000000000..f2add5fc0c
Binary files /dev/null and b/imap_processing/tests/hi/data/l0/imap_hi_l0_raw-memdmp_20260926_v003.pkts differ
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 c96354aaeb..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
@@ -6,26 +6,26 @@
# https://imap-processing.readthedocs.io/en/latest/data-access/calibration-files.html
#
# When creating PSET products, the following table will be used to filter the list
-# of DEs into the into calibration product categories at each ESA energy step. Only
+# of DEs into calibration product categories at each ESA energy step. Only
# 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
new file mode 100644
index 0000000000..1b9329fa11
--- /dev/null
+++ b/imap_processing/tests/hi/data/l1/imap_hi_90sensor-esa-energies_20240101_v001.csv
@@ -0,0 +1,25 @@
+# ESA Energies table
+# 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
+#
+# Values in this file were taken from the mean values extracted by Paul Janzen from
+# data take on Nov 4/24 for Hi90 and Feb 8/25 for Hi45.
+#
+# This file will be used twice in Hi processing:
+# - 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,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,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 75%
rename from imap_processing/tests/hi/test_l1a.py
rename to imap_processing/tests/hi/test_hi_l1a.py
index 88235ece76..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"
@@ -103,6 +132,43 @@ def test_app_hist_decom(hi_l0_test_data_path):
assert cem_raw_cdf_filepath.name.startswith("imap_hi_l1a_90sensor-hist_")
+def test_memdmp_decom(hi_l0_test_data_path):
+ """Test memdmp data"""
+ bin_data_path = hi_l0_test_data_path / "imap_hi_l0_raw-memdmp_20260926_v003.pkts"
+ processed_data = hi_l1a(packet_file_path=bin_data_path)
+
+ # Write CDFs
+ for ds in processed_data:
+ memdmp_filepath = write_cdf(ds)
+ sensor_num = "45" if ds["pkt_apid"].data[0] == HIAPID.H45_MEMDMP else "90"
+ assert memdmp_filepath.name.startswith(
+ f"imap_hi_l1a_{sensor_num}sensor-memdmp_"
+ )
+
+
+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 680304adab..91de0a9cbb 100644
--- a/imap_processing/tests/hi/test_hi_l1b.py
+++ b/imap_processing/tests/hi/test_hi_l1b.py
@@ -3,18 +3,29 @@
from unittest import mock
import numpy as np
+import pandas as pd
import pytest
import xarray as xr
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,
- hi_l1b,
+ get_esa_to_esa_energy_step_lut,
+ housekeeping,
)
-from imap_processing.hi.utils import CoincidenceBitmap, HiConstants
+from imap_processing.hi.utils import (
+ CoincidenceBitmap,
+ EsaEnergyStepLookupTable,
+ HiConstants,
+)
+from imap_processing.quality_flags import ImapHiL1bDeFlags
from imap_processing.spice.geometry import SpiceFrame
@@ -23,31 +34,107 @@ def test_hi_l1b_hk(hi_l0_test_data_path):
housekeeping L1A as input"""
bin_data_path = hi_l0_test_data_path / "H90_NHK_20241104.bin"
- l1b_datasets = hi_l1b(bin_data_path)
+ l1b_datasets = housekeeping(bin_data_path)
assert len(l1b_datasets) == 1
assert l1b_datasets[0].attrs["Logical_source"] == "imap_hi_l1b_90sensor-hk"
-@pytest.mark.external_test_data
@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_hi_l1b_de(
- hi_l1_test_data_path, spice_test_data_path, use_fake_spin_data_for_time
+@pytest.mark.external_test_data
+@mock.patch("imap_processing.hi.hi_l1b.get_esa_to_esa_energy_step_lut")
+def test_hi_annotate_direct_events(
+ mock_get_esa_lut,
+ hi_l1_test_data_path,
+ use_fake_spin_data_for_time,
+ imap_ena_sim_metakernel,
):
- """Test coverage for imap_processing.hi_l1b.hi_l1b() with
- direct events L1A as input"""
+ """Test coverage for imap_processing.hi_l1b.annotate_direct_events() with
+ direct events L1A as input and spice kernel coverage."""
+ # Mock the esa LUT object to map esa_step to the same esa_energy_step value
+ mock_esa_lut = mock.MagicMock(spec=EsaEnergyStepLookupTable())
+ mock_esa_lut.query.side_effect = lambda a, b: b
+ mock_get_esa_lut.return_value = mock_esa_lut
+
# Start MET time of spin for simulated input data is 482372988
use_fake_spin_data_for_time(482372987.999)
l1a_test_file_path = (
hi_l1_test_data_path / "imap_hi_l1a_45sensor-de_20250415_v999.cdf"
)
+ esa_energies_csv = (
+ hi_l1_test_data_path / "imap_hi_90sensor-esa-energies_20240101_v001.csv"
+ )
# Process using test data
l1a_dataset = load_cdf(l1a_test_file_path)
- l1b_datasets = hi_l1b(l1a_dataset)
+ 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
+@mock.patch(
+ "imap_processing.spice.spin.get_spacecraft_to_instrument_spin_phase_offset",
+ return_value=0,
+)
+@mock.patch("imap_processing.hi.hi_l1b.instrument_pointing")
+def test_annotate_direct_events_with_hk(
+ mock_instrument_pointing,
+ mock_inst_phase_offset,
+ hi_l1_test_data_path,
+ use_fake_spin_data_for_time,
+):
+ """Test imap_processing.hi_l1b.annotate_direct_events() with a
+ coincident de and hk dataset but mocked spice."""
+ # Mock instrument pointing to return zeros since we don't have spice kernels
+ # for this time.
+ mock_instrument_pointing.side_effect = lambda et, frame_a, frame_b: np.zeros(
+ (len(et), 3)
+ )
+
+ l1a_de_file_path = (
+ hi_l1_test_data_path / "imap_hi_l1a_90sensor-de_20241105-repoint00099_v001.cdf"
+ )
+ l1b_hk_file_path = (
+ hi_l1_test_data_path / "imap_hi_l1b_90sensor-hk_20241105-repoint00099_v001.cdf"
+ )
+ esa_energies_csv = (
+ hi_l1_test_data_path / "imap_hi_90sensor-esa-energies_20240101_v001.csv"
+ )
+ # Process using test data
+ l1a_dataset = load_cdf(l1a_de_file_path)
+ hk_dataset = load_cdf(l1b_hk_file_path)
+ # Cross-cal data used a 15 second spin period. Calculate start time of first
+ # spin
+ spin_start_met = (
+ l1a_dataset["esa_step_seconds"].data[0].astype(float)
+ + l1a_dataset["esa_step_milliseconds"].data[0].astype(float) / 1000
+ )
+ use_fake_spin_data_for_time(spin_start_met)
+
+ 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) == 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
@@ -92,7 +179,8 @@ def synthetic_trigger_id_and_tof_data():
)
data = [arr[good_inds] for arr in data]
data_vars = {
- n: xr.DataArray(arr, dims=["event_met"]) for n, arr in zip(var_names, data)
+ n: xr.DataArray(arr, dims=["event_met"])
+ for n, arr in zip(var_names, data, strict=False)
}
synthetic_l1a_ds = xr.Dataset(
coords={
@@ -106,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])
@@ -153,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
@@ -201,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
@@ -237,18 +335,531 @@ def side_effect_func(et, inst_frame: SpiceFrame, to_frame):
np.testing.assert_allclose(new_vars["hae_longitude"].values, sensor_number)
-def test_de_esa_energy_step():
+@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, 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
+ mock_get_esa_lut.return_value = mock_esa_lut
+
n_epoch = 20
fake_dataset = xr.Dataset(
coords={
"epoch": xr.DataArray(np.arange(n_epoch), name="epoch", dims=["epoch"])
},
- data_vars={"esa_step": xr.DataArray(np.arange(n_epoch) % 9, dims=["epoch"])},
+ data_vars={
+ "ccsds_met": xr.DataArray(np.arange(n_epoch) % 9, dims=["epoch"]),
+ "esa_step": xr.DataArray(np.arange(n_epoch), dims=["epoch"]),
+ },
)
- esa_energy_step_var = de_esa_energy_step(fake_dataset)
- # TODO: The below check is for the temporary implementation and should be
- # removed when the function is update.
+ esa_energy_step_var = de_esa_energy_step(fake_dataset, xr.Dataset(), "Fake path")
+
np.testing.assert_array_equal(
- esa_energy_step_var["esa_energy_step"].values, fake_dataset.esa_step.values
+ esa_energy_step_var["esa_energy_step"].values, np.arange(n_epoch)[::-1] % 9
)
+
+
+class TestGetEsaToEsaEnergyStepLut:
+ """Test suite for get_esa_to_esa_energy_step_lut function."""
+
+ def setup_method(self):
+ """Set up test fixtures before each test method."""
+ # Mock the EsaEnergyStepLookupTable class
+ self.mock_lut = mock.Mock(spec=EsaEnergyStepLookupTable())
+
+ # Sample ESA energies lookup table
+ self.esa_energies_lut = pd.DataFrame(
+ {
+ "inner_esa_voltage": [-100.0, -200.0, -300.0],
+ "outer_esa_voltage": [50.0, 100.0, 150.0],
+ "inner_esa_delta_v": [5.0, 5.0, 5.0],
+ "outer_esa_delta_v": [2.5, 2.5, 2.5],
+ "esa_energy_step": [1, 2, 3],
+ }
+ )
+
+ def create_mock_dataset(
+ self,
+ op_modes,
+ esa_steps,
+ inner_esa_state,
+ inner_esa_hi,
+ inner_esa_lo,
+ outer_esa_values,
+ shcoarse_values,
+ ):
+ """Helper method to create mock L1B housekeeping dataset."""
+ return xr.Dataset(
+ {
+ "op_mode": (["epoch"], op_modes),
+ "sci_esa_step": (["epoch"], esa_steps),
+ "inner_esa_state": (["epoch"], inner_esa_state),
+ "inner_esa_hi": (["epoch"], inner_esa_hi),
+ "inner_esa_lo": (["epoch"], inner_esa_lo),
+ "outer_esa": (["epoch"], outer_esa_values),
+ "shcoarse": (["epoch"], shcoarse_values),
+ }
+ )
+
+ @mock.patch("imap_processing.hi.hi_l1b.EsaEnergyStepLookupTable")
+ def test_basic_functionality_single_hvsci_segment(self, mock_lut_class):
+ """Test basic functionality with a single HVSCI segment."""
+ mock_lut_class.return_value = self.mock_lut
+
+ # Create test data with single HVSCI segment
+ l1b_hk_ds = self.create_mock_dataset(
+ op_modes=["HVSCI", "HVSCI", "HVSCI", "HVSCI"],
+ esa_steps=[1, 1, 2, 2],
+ inner_esa_state=["HI", "HI", "HI", "HI"],
+ inner_esa_hi=[
+ -98.0,
+ -102.0,
+ -198.0,
+ -202.0,
+ ], # Should match steps 1 and 2
+ inner_esa_lo=[0, 0, 0, 0],
+ outer_esa_values=[49.0, 51.0, 99.0, 101.0],
+ shcoarse_values=[1000, 1001, 1002, 1003],
+ )
+
+ result = get_esa_to_esa_energy_step_lut(l1b_hk_ds, self.esa_energies_lut)
+
+ # Verify LUT was instantiated
+ mock_lut_class.assert_called_once()
+
+ # Verify add_entry was called for each ESA step
+ assert self.mock_lut.add_entry.call_count == 2
+
+ # Check the calls made to add_entry
+ calls = self.mock_lut.add_entry.call_args_list
+
+ # First call should be for esa_step 1
+ assert calls[0][0] == (
+ 1000,
+ 1003,
+ 1,
+ 1,
+ ) # start_time, end_time, esa_step, esa_energy_step
+
+ # Second call should be for esa_step 2
+ assert calls[1][0] == (1000, 1003, 2, 2)
+
+ assert result == self.mock_lut
+
+ @mock.patch("imap_processing.hi.hi_l1b.EsaEnergyStepLookupTable")
+ def test_multiple_hvsci_segments(self, mock_lut_class):
+ """Test with multiple separate HVSCI segments."""
+ mock_lut_class.return_value = self.mock_lut
+
+ l1b_hk_ds = self.create_mock_dataset(
+ op_modes=["OTHER", "HVSCI", "HVSCI", "OTHER", "HVSCI", "HVSCI"],
+ esa_steps=[1, 1, 1, 2, 2, 2],
+ inner_esa_state=["LO", "LO", "LO", "LO", "LO", "LO"],
+ inner_esa_hi=[0, 0, 0, 0, 0, 0],
+ inner_esa_lo=[-100.0, -98.0, -102.0, -200.0, -198.0, -202.0],
+ outer_esa_values=[50.0, 49.0, 51.0, 100.0, 99.0, 101.0],
+ shcoarse_values=[1000, 1001, 1002, 1003, 1004, 1005],
+ )
+
+ _ = get_esa_to_esa_energy_step_lut(l1b_hk_ds, self.esa_energies_lut)
+
+ # Should have 2 calls to add_entry (one for each segment)
+ assert self.mock_lut.add_entry.call_count == 2
+
+ calls = self.mock_lut.add_entry.call_args_list
+ # First segment: indices 1-2, esa_step 1
+ assert calls[0][0] == (1001, 1002, 1, 1)
+ # Second segment: indices 4-5, esa_step 2
+ assert calls[1][0] == (1004, 1005, 2, 2)
+
+ @mock.patch("imap_processing.hi.hi_l1b.EsaEnergyStepLookupTable")
+ def test_no_hvsci_segments(self, mock_lut_class):
+ """Test with no HVSCI segments."""
+ mock_lut_class.return_value = self.mock_lut
+
+ l1b_hk_ds = self.create_mock_dataset(
+ op_modes=["OTHER", "LVSCI", "LVSCI"],
+ esa_steps=[1, 2, 3],
+ inner_esa_state=["HI", "HI", "HI"],
+ inner_esa_hi=[-100.0, -200.0, -300.0],
+ inner_esa_lo=[-100.0, -200.0, -300.0],
+ outer_esa_values=[50.0, 100.0, 150.0],
+ shcoarse_values=[1000, 1001, 1002],
+ )
+
+ result = get_esa_to_esa_energy_step_lut(l1b_hk_ds, self.esa_energies_lut)
+
+ # No add_entry calls should be made
+ self.mock_lut.add_entry.assert_not_called()
+ assert result == self.mock_lut
+
+ @mock.patch("imap_processing.hi.hi_l1b.EsaEnergyStepLookupTable")
+ @mock.patch("imap_processing.hi.hi_l1b.logger")
+ def test_no_voltage_match_found(self, mock_logger, mock_lut_class):
+ """Test when no matching ESA energy is found."""
+ mock_lut_class.return_value = self.mock_lut
+
+ l1b_hk_ds = self.create_mock_dataset(
+ op_modes=["HVSCI", "HVSCI"],
+ esa_steps=[1, 1],
+ inner_esa_state=["HI", "LO"],
+ inner_esa_hi=[-500.0, -500.0], # No match in lookup table
+ inner_esa_lo=[-500.0, -500.0],
+ outer_esa_values=[500.0, 500.0],
+ shcoarse_values=[1000, 1001],
+ )
+
+ _ = get_esa_to_esa_energy_step_lut(l1b_hk_ds, self.esa_energies_lut)
+
+ # Should log critical error
+ mock_logger.critical.assert_called_once()
+ assert (
+ "No esa_energy_step matches found" in mock_logger.critical.call_args[0][0]
+ )
+
+ # No add_entry should be called
+ self.mock_lut.add_entry.assert_not_called()
+
+ @mock.patch("imap_processing.hi.hi_l1b.EsaEnergyStepLookupTable")
+ @mock.patch("imap_processing.hi.hi_l1b.logger")
+ def test_multiple_voltage_matches_found(self, mock_logger, mock_lut_class):
+ """Test when multiple matching ESA energies are found."""
+ mock_lut_class.return_value = self.mock_lut
+
+ # Create lookup table with overlapping voltage ranges
+ overlapping_lut = pd.DataFrame(
+ {
+ "inner_esa_voltage": [-100.0, -102.0], # Overlapping ranges
+ "outer_esa_voltage": [50.0, 52.0],
+ "inner_esa_delta_v": [10.0, 10.0], # Large deltas create overlap
+ "outer_esa_delta_v": [10.0, 10.0],
+ "esa_energy_step": [1, 2],
+ }
+ )
+
+ l1b_hk_ds = self.create_mock_dataset(
+ op_modes=["HVSCI", "HVSCI"],
+ esa_steps=[1, 1],
+ inner_esa_state=["HI", "LO"],
+ inner_esa_hi=[-101.0, 0], # Matches both rows
+ inner_esa_lo=[0, -101.0], # Matches both rows
+ outer_esa_values=[51.0, 51.0],
+ shcoarse_values=[1000, 1001],
+ )
+
+ _ = get_esa_to_esa_energy_step_lut(l1b_hk_ds, overlapping_lut)
+
+ # Should log critical error for multiple matches
+ mock_logger.critical.assert_called_once()
+ assert (
+ "Multiple esa_energy_step matches found"
+ in mock_logger.critical.call_args[0][0]
+ )
+
+ # No add_entry should be called
+ self.mock_lut.add_entry.assert_not_called()
+
+ @mock.patch("imap_processing.hi.hi_l1b.EsaEnergyStepLookupTable")
+ def test_single_data_point_segment(self, mock_lut_class):
+ """Test with HVSCI segment containing only one data point."""
+ mock_lut_class.return_value = self.mock_lut
+
+ l1b_hk_ds = self.create_mock_dataset(
+ op_modes=["HVSCI"],
+ esa_steps=[1],
+ inner_esa_state=["HI"],
+ inner_esa_hi=[-100.0],
+ inner_esa_lo=[-100.0],
+ outer_esa_values=[50.0],
+ shcoarse_values=[1000],
+ )
+
+ _ = get_esa_to_esa_energy_step_lut(l1b_hk_ds, self.esa_energies_lut)
+
+ # Should still work with single data point
+ self.mock_lut.add_entry.assert_called_once_with(1000, 1000, 1, 1)
+
+ @mock.patch("imap_processing.hi.hi_l1b.EsaEnergyStepLookupTable")
+ def test_esa_step_not_in_segment(self, mock_lut_class):
+ """Test when an ESA step doesn't appear in a particular HVSCI segment."""
+ mock_lut_class.return_value = self.mock_lut
+
+ l1b_hk_ds = self.create_mock_dataset(
+ op_modes=["OTHER", "HVSCI", "HVSCI", "OTHER"],
+ esa_steps=[1, 2, 2, 1], # ESA step 1 not in HVSCI segment
+ inner_esa_state=["HI", "HI", "HI", "HI"],
+ inner_esa_hi=[-100.0, -198.0, -202.0, -100.0],
+ inner_esa_lo=[0, 0, 0, 0],
+ outer_esa_values=[50.0, 99.0, 101.0, 50.0],
+ shcoarse_values=[1000, 1001, 1002, 1003],
+ )
+
+ _ = get_esa_to_esa_energy_step_lut(l1b_hk_ds, self.esa_energies_lut)
+
+ # Only ESA step 2 should be processed (it's the only one in HVSCI segment)
+ self.mock_lut.add_entry.assert_called_once_with(1001, 1002, 2, 2)
+
+ @pytest.mark.external_test_data
+ def test_cal_data(self, hi_l1_test_data_path):
+ """Test with calibration data."""
+ l1b_hk_ds = load_cdf(
+ hi_l1_test_data_path
+ / "imap_hi_l1b_90sensor-hk_20241105-repoint00099_v001.cdf"
+ )
+ # Create a esa energies pandas DataFrame
+ esa_energies_lut_data = {
+ "esa_energy_step": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+ "nominal_central_energy": [
+ np.nan,
+ 0.50,
+ 0.75,
+ 1.10,
+ 1.65,
+ 2.50,
+ 3.75,
+ 5.70,
+ 8.52,
+ 12.8,
+ ],
+ "inner_esa_voltage": [
+ 0,
+ -472,
+ -713,
+ -1010,
+ -1524,
+ -2060,
+ -2870,
+ -4107,
+ -5908,
+ -8625,
+ ],
+ "inner_esa_delta_v": [25, 25, 25, 25, 25, 25, 25, 25, 25, 25],
+ "outer_esa_voltage": [0, 122, 164, 213, 270, 718, 1232, 2034, 3185, 4911],
+ "outer_esa_delta_v": [25, 25, 25, 25, 25, 25, 25, 25, 25, 25],
+ }
+ esa_energies_lut = pd.DataFrame(esa_energies_lut_data)
+
+ lut = get_esa_to_esa_energy_step_lut(l1b_hk_ds, esa_energies_lut)
+
+ # 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 da9841d998..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,41 +11,77 @@
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 == {}
-@pytest.mark.external_test_data
@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
+@pytest.mark.external_test_data
def test_generate_pset_dataset(
- hi_l1_test_data_path, hi_test_cal_prod_config_path, use_fake_spin_data_for_time
+ 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))
@@ -62,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"])
@@ -127,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
@@ -154,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"]),
@@ -244,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 = (
@@ -257,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
@@ -270,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(
@@ -301,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")
@@ -344,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)
@@ -371,35 +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"]
- ):
- 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 4f37e83d5d..12bd805147 100644
--- a/imap_processing/tests/hi/test_hi_l2.py
+++ b/imap_processing/tests/hi/test_hi_l2.py
@@ -1,33 +1,44 @@
"""Test coverage for imap_processing.hi.l2.hi_l2.py"""
+from unittest import mock
+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,
- 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],
)
@@ -37,13 +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
-def test_hi_l2(hi_l1_test_data_path):
+@pytest.mark.external_kernel
+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"
- l2_dataset = hi_l2([pset_path], None, None, "h90-ena-h-sf-nsp-full-hae-4deg-3mo")[0]
+
+ l2_dataset = hi_l2(
+ [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"]
)
@@ -52,25 +185,133 @@ def test_hi_l2(hi_l1_test_data_path):
@pytest.mark.external_test_data
-def test_genarate_hi_map(hi_l1_test_data_path):
- """Test coverage for genarate_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_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"
- sky_map = generate_hi_map(
- [pset_path], None, None, cg_corrected=False, direction="full", map_spacing=6
+ descriptor_str = "h90-ena-h-sf-nsp-full-hnu-2deg-3mo"
+ 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, descriptor_str)[0]
+
+ assert rect_map.spice_reference_frame == SpiceFrame.IMAP_HNU
+ assert rect_map.spacing_deg == 2.0
+
+ mock_map_build_cdf_dataset.assert_called_with(
+ rect_map, "hi", "l2", descriptor_str, sensor="90"
)
- assert isinstance(sky_map, RectangularSkyMap)
- assert sky_map.spacing_deg == 6
- # 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
+
+@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_create_sky_map_from_psets(
+ hi_l1_test_data_path,
+ anc_path_dict,
+ furnish_kernels,
+ descriptor_str,
+ expected_keys,
+):
+ """Test coverage for create_sky_map_from_psets()"""
+ kernels = [
+ "imap_sclk_0000.tsc",
+ "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"
+
+ map_descriptor = MapDescriptor.from_string(descriptor_str)
+ sky_maps = create_sky_map_from_psets(
+ [pset_path],
+ anc_path_dict,
+ map_descriptor,
+ )
+
+ # 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,
+ )
+
+
+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"}
@@ -92,32 +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):
- """Test coverage for calculate_ena_intensity"""
+@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(
@@ -133,19 +377,1221 @@ def test_calculate_ena_intensity(empty_rectangular_map_dataset):
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, None)
- # 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
+
+
+@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])
+ 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 68841c2743..78abfb5607 100644
--- a/imap_processing/tests/hi/test_utils.py
+++ b/imap_processing/tests/hi/test_utils.py
@@ -1,15 +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,
)
@@ -122,3 +135,1462 @@ def test_create_dataset_variables(var_names, shape, fill_value, lookup_str):
def test_coincidence_type_string_to_int(sensor_hit_str, expected_val):
"""Test coverage for coincidence_type_string_to_int function"""
assert CoincidenceBitmap.detector_hit_str_to_int(sensor_hit_str) == expected_val
+
+
+class TestEsaEnergyStepLookupTable:
+ """Test suite for EsaEnergyStepLookupTable class."""
+
+ @pytest.fixture
+ def empty_lookup(self):
+ """Create an empty lookup table for testing."""
+ return EsaEnergyStepLookupTable()
+
+ @pytest.fixture
+ def populated_lookup(self):
+ """Create a lookup table with test data."""
+ lookup = EsaEnergyStepLookupTable()
+ # Columns are: [start_met, end_met, esa_step, esa_energy_step]
+ entries = [
+ (0.0, 10.0, 1, 100.0),
+ (0.0, 10.0, 2, 200.0),
+ (10.0, 20.0, 1, 150.0),
+ (10.0, 20.0, 2, 250.0),
+ ]
+ for entry in entries:
+ lookup.add_entry(*entry)
+ return lookup
+
+ def test_init(self, empty_lookup):
+ """Test initialization of lookup table."""
+ assert len(empty_lookup.df) == 0
+ assert list(empty_lookup.df.columns) == [
+ "start_met",
+ "end_met",
+ "esa_step",
+ "esa_energy_step",
+ ]
+ assert empty_lookup._indexed is False
+
+ def test_add_entry_single(self, empty_lookup):
+ """Test adding a single entry."""
+ empty_lookup.add_entry(0.0, 10.0, 1, 100.0)
+
+ assert len(empty_lookup.df) == 1
+ assert empty_lookup.df.iloc[0]["start_met"] == 0.0
+ assert empty_lookup.df.iloc[0]["end_met"] == 10.0
+ assert empty_lookup.df.iloc[0]["esa_step"] == 1
+ assert empty_lookup.df.iloc[0]["esa_energy_step"] == 100.0
+ assert empty_lookup._indexed is False
+
+ def test_add_entry_multiple(self, empty_lookup):
+ """Test adding multiple entries one by one."""
+ empty_lookup.add_entry(0.0, 10.0, 1, 100.0)
+ empty_lookup.add_entry(10.0, 20.0, 2, 200.0)
+
+ assert len(empty_lookup.df) == 2
+ assert empty_lookup._indexed is False
+
+ def test_ensure_indexed(self, populated_lookup):
+ """Test the indexing functionality."""
+ # Initially not indexed
+ assert populated_lookup._indexed is False
+
+ # Call _ensure_indexed
+ populated_lookup._ensure_indexed()
+ assert populated_lookup._indexed is True
+
+ # Check that data is sorted by start_met, then esa_step
+ df = populated_lookup.df
+ # np.lexsort uses the last key as the primary sort order
+ np.testing.assert_array_equal(
+ np.lexsort((df["esa_step"].values, df["start_met"].values)),
+ np.arange(len(df)),
+ )
+
+ def test_query_scalar_found(self, populated_lookup):
+ """Test scalar query that finds a match."""
+ result = populated_lookup.query(5.0, 1)
+ assert result == 100.0
+
+ result = populated_lookup.query(12.0, 2)
+ assert result == 250.0
+
+ def test_query_scalar_not_found(self, populated_lookup):
+ """Test scalar query that doesn't find a match."""
+ # Query outside time range
+ result = populated_lookup.query(25.0, 1)
+ assert result == 255
+
+ # Query with non-existent esa_step
+ result = populated_lookup.query(5.0, 99)
+ assert result == 255
+
+ def test_query_array_found(self, populated_lookup):
+ """Test array query with matches."""
+ mets = [5.0, 12.0, 8.0]
+ steps = [1, 2, 3]
+ results = populated_lookup.query(mets, steps)
+
+ assert isinstance(results, np.ndarray)
+ assert len(results) == 3
+ assert results[0] == 100 # MET=5.0, step=1
+ assert results[1] == 250 # MET=12.0, step=2
+ assert results[2] == 255 # MET=8.0, step=3
+
+ def test_query_array_all_not_found(self, populated_lookup):
+ """Test array query where no entries are found."""
+ mets = [25.0, 30.0]
+ steps = [1, 2]
+ results = populated_lookup.query(mets, steps)
+
+ assert isinstance(results, np.ndarray)
+ assert len(results) == 2
+ assert results[0] == 255
+ assert results[1] == 255
+
+ def test_query_numpy_arrays(self, populated_lookup):
+ """Test query with numpy arrays as input."""
+ mets = np.array([5.0, 12.0])
+ steps = np.array([1, 2])
+ results = populated_lookup.query(mets, steps)
+
+ assert isinstance(results, np.ndarray)
+ assert len(results) == 2
+ assert results[0] == 100.0
+ assert results[1] == 250.0
+
+ def test_query_mixed_scalar_array_raises_error(self, populated_lookup):
+ """Test that mixing scalar and array inputs raises ValueError."""
+ with pytest.raises(
+ ValueError,
+ match="query_met and esa_step must both be scalars or both be array-like",
+ ):
+ populated_lookup.query(5.0, [1, 2])
+
+ with pytest.raises(
+ ValueError,
+ match="query_met and esa_step must both be scalars or both be array-like",
+ ):
+ populated_lookup.query([5.0, 12.0], 1)
+
+ def test_query_different_length_arrays_raises_error(self, populated_lookup):
+ """Test that arrays of different lengths raise ValueError."""
+ with pytest.raises(
+ ValueError,
+ match="query_met and esa_step must have the same length "
+ "when both are array-like",
+ ):
+ populated_lookup.query([5.0, 12.0], [1, 2, 3])
+
+ with pytest.raises(
+ ValueError,
+ match="query_met and esa_step must have the same length "
+ "when both are array-like",
+ ):
+ populated_lookup.query([5.0, 12.0, 8.0], [1, 2])
+
+ def test_query_different_shape_arrays_raises_error(self, populated_lookup):
+ """Test that arrays of different shapes raise ValueError."""
+ mets = np.array([[5.0, 12.0]]) # Shape (1, 2)
+ steps = np.array([1, 2]) # Shape (2,)
+
+ with pytest.raises(
+ ValueError,
+ match="query_met and esa_step must have the same "
+ "length when both are array-like",
+ ):
+ populated_lookup.query(mets, steps)
+
+ def test_query_single_element_arrays(self, populated_lookup):
+ """Test query with single-element arrays."""
+ results = populated_lookup.query([5.0], [1])
+ assert isinstance(results, np.ndarray)
+ assert len(results) == 1
+ assert results[0] == 100.0
+
+ def test_query_calls_ensure_indexed(self, populated_lookup):
+ """Test that query calls _ensure_indexed."""
+ # Reset indexed flag
+ populated_lookup._indexed = False
+
+ # Call query
+ populated_lookup.query(5.0, 1)
+
+ # Check that indexing was performed
+ assert populated_lookup._indexed is True
+
+ def test_add_entry_resets_indexed_flag(self, populated_lookup):
+ """Test that adding entries resets the indexed flag."""
+ # Ensure it's indexed first
+ populated_lookup._ensure_indexed()
+ assert populated_lookup._indexed is True
+
+ # Add entry
+ populated_lookup.add_entry(20.0, 30.0, 4, 400.0)
+ assert populated_lookup._indexed is False
+
+ def test_edge_case_boundary_values(self, populated_lookup):
+ """Test queries at exact boundary values."""
+ # Test exact start time
+ result = populated_lookup.query(0.0, 1)
+ assert result == 100.0
+
+ # Test exact end time
+ 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 55c2d2c1d2..1038de7c33 100644
--- a/imap_processing/tests/hit/helpers/l1_validation.py
+++ b/imap_processing/tests/hit/helpers/l1_validation.py
@@ -305,19 +305,56 @@ 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
+def compare_sectored_data(frame, species, energy_bin, actual_data, expected_data):
+ """Compare sectored data for a specific frame, species, and energy bin."""
+ if "sectorates_stat_uncert_plus" in expected_data.columns:
+ np.testing.assert_allclose(
+ actual_data[f"{species}_sectored_counts_stat_uncert_plus"][frame][
+ energy_bin
+ ].data,
+ expected_data["sectorates_stat_uncert_plus"][frame],
+ rtol=1e-7,
+ atol=1e-8,
+ err_msg=f"Mismatch in {species}_sectored_counts_stat_uncert_plus "
+ f"at frame {frame}, energy_bin {energy_bin}",
+ )
+ if "sectorates_stat_uncert_minus" in expected_data.columns:
+ np.testing.assert_allclose(
+ actual_data[f"{species}_sectored_counts_stat_uncert_minus"][frame][
+ energy_bin
+ ].data,
+ expected_data["sectorates_stat_uncert_minus"][frame],
+ rtol=1e-7,
+ atol=1e-8,
+ err_msg=f"Mismatch in {species}_sectored_counts_stat_uncert_minus at "
+ f"frame {frame}, energy_bin {energy_bin}",
+ )
+ else:
+ np.testing.assert_allclose(
+ actual_data[f"{species}_sectored_counts"][frame][energy_bin].data,
+ expected_data["sectorates"][frame],
+ rtol=1e-7,
+ atol=1e-8,
+ err_msg=f"Mismatch in {species}_sectored_counts at frame {frame}, "
+ f"energy_bin {energy_bin}",
+ )
+
+
def compare_data(
expected_data: pd.DataFrame, actual_data: xr.Dataset, skip: list[str]
) -> None:
@@ -331,76 +368,44 @@ def compare_data(
actual_data : xr.Dataset
Processed counts data from l1a processing
skip : list
- Fields to skip in comparison
+ Data variables to skip in comparison
"""
- for field in expected_data.columns:
- if field not in [
- "sc_tick_by_frame",
- "species",
- "energy_bin",
- ]:
- assert field in actual_data.data_vars.keys(), (
- f"Field {field} not found in actual data variables"
- )
- if field not in skip:
- for frame in range(expected_data.shape[0]):
- if field == "species":
- # Compare sectored rates data using species and energy index.
- # which are only present in the validation data. In the actual
- # data, sectored rates are organized by species in 4D arrays.
- # i.e. h_sectored_counts has shape
- # (epoch, h_energy_index, azimuth, zenith).
- # species and energy index are used to find the correct
- # array of sectored rate data from the actual data for comparison.
- species = expected_data[field][frame]
+ for var in expected_data.columns:
+ if var not in skip:
+ if var not in ["sc_tick_by_frame", "species"]:
+ # Check if the var is in the processed dataset
+ assert var in actual_data.data_vars.keys(), (
+ f"Field {var} not found in actual data variables"
+ )
+ # Compare data arrays
+ np.testing.assert_allclose(
+ actual_data[var].values,
+ np.stack(expected_data[var].values),
+ rtol=1e-7,
+ atol=1e-8,
+ err_msg=f"Mismatch in {var}",
+ )
+ if var == "sc_tick_by_frame":
+ # Get the sc_tick values for each frame in the actual data
+ # to compare with the expected data
+ sc_tick = actual_data.sc_tick.values
+ sc_tick_by_frame = sc_tick[::20]
+ assert np.array_equal(sc_tick_by_frame, expected_data[var].values), (
+ f"Mismatch in {var}"
+ )
+ if var == "species" and "sectored" in actual_data.Logical_source:
+ # Compare sectored rates data using species and energy bin,
+ # which are only present in the validation data. In the actual
+ # data, sectored rates are organized by species in 4D arrays.
+ # i.e. h_sectored_counts has shape
+ # (epoch, h_energy_index, azimuth, zenith).
+ # species and energy bin are used to find the correct
+ # array of sectored rate data from the actual data for comparison.
+ # Check science frame by science frame. A science frame is a row in
+ # the validation data.
+ for frame in range(expected_data.shape[0]):
+ species = expected_data[var][frame]
energy_bin = expected_data["energy_bin"][frame]
- if "sectorates_stat_uncert_plus" in expected_data.columns:
- np.testing.assert_allclose(
- actual_data[f"{species}_sectored_counts_stat_uncert_plus"][
- frame
- ][energy_bin].data,
- expected_data["sectorates_stat_uncert_plus"][frame],
- rtol=1e-7, # relative tolerance
- atol=1e-8, # absolute tolerance
- err_msg=f"Mismatch in {species}_sectored_counts_stat_uncert"
- f"_plus at frame {frame}, energy_bin {energy_bin}",
- )
- if "sectorates_stat_uncert_minus" in expected_data.columns:
- np.testing.assert_allclose(
- actual_data[f"{species}_sectored_counts_stat_uncert_minus"][
- frame
- ][energy_bin].data,
- expected_data["sectorates_stat_uncert_minus"][frame],
- rtol=1e-7,
- atol=1e-8,
- err_msg=f"Mismatch in {species}_sectored_counts_stat_uncert"
- f"_minus at frame {frame}, energy_bin {energy_bin}",
- )
- else:
- np.testing.assert_allclose(
- actual_data[f"{species}_sectored_counts"][frame][
- energy_bin
- ].data,
- expected_data["sectorates"][frame],
- rtol=1e-7,
- atol=1e-8,
- err_msg=f"Mismatch in {species}_sectored_counts at"
- f"frame {frame}, energy_bin {energy_bin}",
- )
- elif field == "sc_tick_by_frame":
- # Get the sc_tick values for each frame in the actual data
- # to compare with the validation data
- sc_tick = actual_data.sc_tick.values
- sc_tick_by_frame = sc_tick[::20]
- assert np.array_equal(
- sc_tick_by_frame[frame], expected_data[field][frame]
- ), f"Mismatch in {field} at frame {frame}"
-
- else:
- np.testing.assert_allclose(
- actual_data[field][frame].data,
- expected_data[field][frame],
- rtol=1e-7,
- atol=1e-8,
- err_msg=f"Mismatch in {field} at frame {frame}",
+ compare_sectored_data(
+ frame, species, energy_bin, actual_data, expected_data
)
diff --git a/imap_processing/tests/hit/test_hit_l1a.py b/imap_processing/tests/hit/test_hit_l1a.py
index 7f61fcc9c1..13c672a9b9 100644
--- a/imap_processing/tests/hit/test_hit_l1a.py
+++ b/imap_processing/tests/hit/test_hit_l1a.py
@@ -1,3 +1,4 @@
+from pathlib import Path
from unittest.mock import Mock
import numpy as np
@@ -14,8 +15,13 @@
add_cdf_attributes,
calculate_uncertainties,
decom_hit,
+ filter_dataset_to_processing_day,
+ find_complete_mod10_sets,
hit_l1a,
subcom_sectorates,
+ subset_livetime,
+ subset_sectored_counts,
+ update_livetime_coord,
)
from imap_processing.tests.hit.helpers.l1_validation import (
compare_data,
@@ -30,13 +36,13 @@
@pytest.fixture(scope="module")
def hk_packet_filepath():
"""Set path to test data file"""
- return imap_module_directory / "tests/hit/test_data/hskp_sample.ccsds"
+ return Path(imap_module_directory / "tests/hit/test_data/hskp_sample.ccsds")
@pytest.fixture(scope="module")
def sci_packet_filepath():
"""Set path to test data file"""
- return imap_module_directory / "tests/hit/test_data/sci_sample.ccsds"
+ return Path(imap_module_directory / "tests/hit/test_data/sci_sample.ccsds")
@pytest.fixture(scope="module")
@@ -92,6 +98,152 @@ def test_subcom_sectorates(sci_packet_filepath):
assert sci_dataset[f"{species}_energy_delta_plus"].shape == (shape[0],)
+def test_update_livetime_coord():
+ """Test the update_livetime_coord function."""
+
+ # Create a mock dataset with livetime_counter and epoch
+ epoch_values = np.array([1, 2, 3, 4, 5])
+ livetime_values = np.array([10, 20, 30, 40, 50])
+
+ sectored_dataset = xr.Dataset(
+ {
+ "livetime_counter": ("epoch", livetime_values),
+ },
+ coords={
+ "epoch": epoch_values,
+ },
+ )
+
+ # Call the function
+ updated_dataset = update_livetime_coord(sectored_dataset)
+
+ # Assert the new coordinate 'epoch_livetime' exists
+ assert "epoch_livetime" in updated_dataset.coords
+
+ # Assert the values of 'epoch_livetime' match the original epoch values
+ np.testing.assert_array_equal(
+ updated_dataset["epoch_livetime"].values, epoch_values
+ )
+
+ # Assert the dimension of 'livetime_counter' is swapped to 'epoch_livetime'
+ assert updated_dataset["livetime_counter"].dims == ("epoch_livetime",)
+
+ # Assert the values of 'livetime_counter' remain unchanged
+ np.testing.assert_array_equal(
+ updated_dataset["livetime_counter"].values, livetime_values
+ )
+
+ # Assert the original 'epoch' coordinate is still present
+ assert "epoch" in updated_dataset.coords
+
+
+def test_subset_livetime():
+ """Test the subset_livetime function."""
+
+ # Test case 1: Normal case with valid epoch and epoch_livetime sizes
+
+ # epoch_livetime goes from 0 to 59 (simulates 60 minutes)
+ epoch_livetime = np.arange(60)
+
+ # epoch is 30 minute subset of epoch_livetime
+ epoch = epoch_livetime[10:40]
+
+ dataset = xr.Dataset(
+ {
+ "livetime_counter": xr.DataArray(
+ np.arange(60),
+ dims=["epoch_livetime"],
+ coords={"epoch_livetime": epoch_livetime},
+ )
+ },
+ coords={"epoch": epoch, "epoch_livetime": epoch_livetime},
+ )
+
+ # Call the function
+ trimmed = subset_livetime(dataset)
+
+ # The trimmed livetime should match the slice from index 0 to 29 (inclusive)
+ expected_indices = slice(0, 30)
+ expected_livetime = dataset.isel(epoch_livetime=expected_indices)
+
+ # Validate the result
+ np.testing.assert_array_equal(
+ trimmed["epoch_livetime"].values, expected_livetime["epoch_livetime"].values
+ )
+ np.testing.assert_array_equal(
+ trimmed["livetime_counter"].values, expected_livetime.livetime_counter.values
+ )
+
+ # Test case 2: epoch is empty, the function should raise a ValueError
+ dataset = xr.Dataset(
+ {
+ "livetime_counter": ("epoch_livetime", np.array([10, 20, 30])),
+ },
+ coords={
+ "epoch": np.array([]),
+ "epoch_livetime": np.array([0, 1, 2]),
+ },
+ )
+ with pytest.raises(
+ ValueError,
+ match="Epoch values are empty. Cannot proceed with livetime subsetting.",
+ ):
+ subset_livetime(dataset)
+
+ # Test case 3: Not enough livetime values, the function should raise a ValueError
+ dataset = xr.Dataset(
+ {
+ "livetime_counter": ("epoch_livetime", np.array([10, 20, 30, 40, 50])),
+ },
+ coords={
+ "epoch": np.array([1, 2, 3]),
+ "epoch_livetime": np.array([0, 1, 2, 3, 4]),
+ },
+ )
+ with pytest.raises(
+ ValueError,
+ match="Start index for livetime is less than 10. This indicates that the "
+ "dataset is too small to shift livetime correctly.",
+ ):
+ subset_livetime(dataset)
+
+
+def test_find_complete_mod10_sets():
+ """Test the find_complete_mod10_sets function."""
+
+ # Test case 1: Valid pattern exists throughout
+ mod_vals = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+ expected_indices = np.array([0, 10])
+ result = find_complete_mod10_sets(mod_vals)
+ assert np.array_equal(result, expected_indices), (
+ f"Expected {expected_indices}, got {result}"
+ )
+
+ # Test case 2: No valid pattern
+ mod_vals = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6])
+ expected_indices = np.array([])
+ result = find_complete_mod10_sets(mod_vals)
+ assert np.array_equal(result, expected_indices), (
+ f"Expected {expected_indices}, got {result}"
+ )
+
+ # Test case 3: Pattern in the middle
+ mod_vals = np.array([5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4])
+ expected_indices = np.array([5])
+ result = find_complete_mod10_sets(mod_vals)
+ assert np.array_equal(result, expected_indices), (
+ f"Expected {expected_indices}, got {result}"
+ )
+
+ # Test case 4: Empty input
+ mod_vals = np.array([])
+ expected_indices = np.array([])
+ result = find_complete_mod10_sets(mod_vals)
+ assert np.array_equal(result, expected_indices), (
+ f"Expected {expected_indices}, got {result}"
+ )
+
+
def test_calculate_uncertainties():
"""Test the calculate_uncertainties function.
@@ -172,6 +324,181 @@ def fake_get_variable_attributes(name, check_schema=True):
assert list(result[f"{dim}_label"].dims) == [f"{dim}"]
+def test_filter_dataset_to_processing_day():
+ """Test the filter_dataset_to_processing_day function."""
+
+ # Create a mock dataset
+ epoch_values = np.array(
+ [
+ 316008024684000000, # 2010-01-05T23:59:18.500
+ 316008084684000000, # 2010-01-06T00:10:18.500
+ 316094424684000000, # 2010-01-06T23:59:18.500
+ 316094484684000000, # 2010-01-07T00:10:18.500
+ ]
+ )
+
+ sc_tick_values = np.array(
+ [
+ 431999, # 2010-01-05T23:59:59.000000000
+ 432002, # 2010-01-06T00:00:02.000000000
+ 518399, # 2010-01-06T23:59:59.000000000
+ 518402, # 2010-01-07T00:00:02.000000000
+ ]
+ )
+
+ dataset = xr.Dataset(
+ {
+ "var1": (["epoch"], np.arange(len(epoch_values))),
+ "var2": (["sc_tick"], np.arange(len(sc_tick_values)) * 2),
+ },
+ coords={
+ "epoch": epoch_values,
+ "sc_tick": sc_tick_values,
+ },
+ )
+
+ # Define the packet date
+ packet_date = "20100106"
+
+ # Call the function
+ filtered_dataset = filter_dataset_to_processing_day(
+ dataset, packet_date, epoch_vals=epoch_values, sc_tick=True
+ )
+
+ # Assert the filtered dataset contains only data within the processing day
+ expected_epochs = np.array(
+ [
+ 316008084684000000, # 2010-01-06T00:10:18.500
+ 316094424684000000, # 2010-01-06T23:59:18.500
+ ]
+ )
+ assert np.array_equal(filtered_dataset["epoch"].values, expected_epochs)
+
+ # Assert the sc_tick values are filtered correctly
+ expected_sc_ticks = np.array([432002, 518399])
+ assert np.array_equal(filtered_dataset["sc_tick"].values, expected_sc_ticks)
+
+
+def test_subset_sectored_counts():
+ """Test the subset_sectored_counts function."""
+
+ def create_l1a_counts_dataset(hdr_minute_cnt_values):
+ """Helper to create L1A counts dataset."""
+ return xr.Dataset(
+ {
+ "hdr_minute_cnt": ("epoch", hdr_minute_cnt_values),
+ "h_sectored_counts": ("epoch", np.arange(len(hdr_minute_cnt_values))),
+ "he4_sectored_counts": ("epoch", np.arange(len(hdr_minute_cnt_values))),
+ "livetime_counter": ("epoch", np.arange(len(hdr_minute_cnt_values))),
+ },
+ coords={
+ "epoch": np.arange(
+ 316008084684000000, 316008084684000000 + len(hdr_minute_cnt_values)
+ ),
+ },
+ )
+
+ def validate_subset(l1a_counts_dataset):
+ """Helper to validate the subset results."""
+ # Define the packet date
+ packet_date = "20100106"
+ subset_dataset = subset_sectored_counts(l1a_counts_dataset, packet_date)
+ assert subset_dataset.sizes["epoch"] == 10
+ assert subset_dataset.sizes["epoch_livetime"] == 10
+ assert np.all(subset_dataset["hdr_minute_cnt"].values % 10 == np.arange(10))
+ assert np.all(
+ subset_dataset["epoch_livetime"].values
+ == subset_dataset["epoch"].values - 10
+ ), "epoch_livetime values are not shifted by 10 from epoch values"
+
+ # Test with partial data at the start and end of the dataset
+ l1a_counts_dataset = create_l1a_counts_dataset(np.arange(105, 135))
+ validate_subset(l1a_counts_dataset)
+
+ # Test with partial data in the middle of the dataset
+ l1a_counts_dataset = create_l1a_counts_dataset(
+ [
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ ]
+ )
+ validate_subset(l1a_counts_dataset)
+
+ # Test with partial data at the start, middle, and end of the dataset
+ l1a_counts_dataset = create_l1a_counts_dataset(
+ [
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 120,
+ 121,
+ 122,
+ 130,
+ 131,
+ 132,
+ 133,
+ 134,
+ 135,
+ 136,
+ 137,
+ 138,
+ 139,
+ 140,
+ 141,
+ ]
+ )
+ validate_subset(l1a_counts_dataset)
+
+ # Test with only partial data in the dataset
+ l1a_counts_dataset = create_l1a_counts_dataset(np.arange(100, 160, 2))
+ with pytest.raises(
+ ValueError,
+ match="No data to process - valid start indices not found for "
+ "complete sectored counts.",
+ ):
+ subset_sectored_counts(l1a_counts_dataset, packet_date="20100106")
+
+
def test_validate_l1a_housekeeping_data(hk_packet_filepath):
"""Validate the housekeeping dataset created by the L1A processing.
@@ -183,7 +510,7 @@ def test_validate_l1a_housekeeping_data(hk_packet_filepath):
hk_packet_filepath : str
File path to housekeeping ccsds file
"""
- datasets = hit_l1a(hk_packet_filepath)
+ datasets = hit_l1a(hk_packet_filepath, "20100105")
hk_dataset = None
for dataset in datasets:
if dataset.attrs["Logical_source"] == "imap_hit_l1a_hk":
@@ -249,10 +576,11 @@ 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.
- This test compares the counts data product with the validation data.
+ This test compares the counts data products with the validation data.
The PHA data product is not validated since it's not being decommutated.
Since the validation data is structured differently than the processed data,
@@ -260,6 +588,13 @@ def test_validate_l1a_counts_data(sci_packet_filepath, validation_data):
functions to consolidate the data into arrays and rename columns to match
the processed data.
+ Additionally, since standard counts, sectored counts, and the livetime values
+ related to the sectored counts all have different time ranges, validation data
+ is further split into three parts:
+ - Standard counts validation
+ - Sectored counts validation
+ - Livetime validation
+
Parameters
----------
sci_packet_filepath : str
@@ -267,18 +602,40 @@ def test_validate_l1a_counts_data(sci_packet_filepath, validation_data):
validation_data : pd.DataFrame
Preloaded validation data
"""
-
- # Process the sample data
- processed_datasets = hit_l1a(sci_packet_filepath)
- l1a_counts_data = processed_datasets[0]
+ # TODO: consider parameterization to test both the instrument
+ # file and fake data file
# Prepare validation data for comparison with processed data
validation_data = prepare_counts_validation_data(validation_data)
- # Fields to skip in comparison. CCSDS headers plus a few others.
- # The CCSDS header fields contain data per packet in the dataset, but the
- # validation data has one value per science frame.
- skip_fields = [
+ # Copy the validation data for sectored data validation.
+ # The first complete set of sectored data with sufficient livetime
+ # data available is from index 17 to -4. Slice the validation data.
+ sectored_validation_data = validation_data.iloc[17:-4].copy().reset_index(drop=True)
+
+ # The corresponding livetime values for the sectored data is from index 7 to -14
+ # (i.e. 10 minutes before the first complete set of sectored data).
+ livetime_validation_data = (
+ validation_data[["livetime_counter"]].iloc[7:-14].copy().reset_index(drop=True)
+ )
+
+ # NOTE: slicing indices are specific to the sci_sample_raw.csv validation file
+
+ # Process the sample data into datasets to be validated
+ processed_datasets = hit_l1a(sci_packet_filepath, packet_date="20100105")
+ standard_counts_data = processed_datasets[0]
+ sectored_counts_data = processed_datasets[1]
+
+ # The validation data contains all science data variables for both
+ # standard and sectored datasets. When comparing each dataset to the
+ # validation data, a list of variables to skip in the comparison is
+ # provided. This is to avoid comparing variables that are not present
+ # in the dataset or are not relevant for the comparison. Variables to
+ # skip in comparison also includes CCSDS headers the datasets contain
+ # data per packet, but the validation data contains one value per
+ # science frame (20 packets)
+
+ skip_vars = [
"version",
"type",
"sec_hdr_flg",
@@ -289,35 +646,218 @@ def test_validate_l1a_counts_data(sci_packet_filepath, validation_data):
"energy_bin",
]
- # Compare processed data to validation data
+ skip_standard_vars = [
+ "hdr_unit_num",
+ "hdr_frame_version",
+ "hdr_leak_conv",
+ "hdr_heater_duty_cycle",
+ "hdr_code_ok",
+ "livetime_counter",
+ "num_trig",
+ "num_reject",
+ "num_acc_w_pha",
+ "num_acc_no_pha",
+ "num_haz_trig",
+ "num_haz_reject",
+ "num_haz_acc_w_pha",
+ "num_haz_acc_no_pha",
+ "sngrates",
+ "nread",
+ "nhazard",
+ "nadcstim",
+ "nodd",
+ "noddfix",
+ "nmulti",
+ "nmultifix",
+ "nbadtraj",
+ "nl2",
+ "nl3",
+ "nl4",
+ "npen",
+ "nformat",
+ "naside",
+ "nbside",
+ "nerror",
+ "nbadtags",
+ "coinrates",
+ "pbufrates",
+ "l2fgrates",
+ "l2bgrates",
+ "l3fgrates",
+ "l3bgrates",
+ "penfgrates",
+ "penbgrates",
+ "ialirtrates",
+ "l4fgrates",
+ "l4bgrates",
+ "nbside_stat_uncert_plus",
+ "nbside_stat_uncert_minus",
+ "l2fgrates_stat_uncert_plus",
+ "l2fgrates_stat_uncert_minus",
+ "noddfix_stat_uncert_plus",
+ "noddfix_stat_uncert_minus",
+ "num_haz_acc_no_pha_stat_uncert_plus",
+ "num_haz_acc_no_pha_stat_uncert_minus",
+ "ialirtrates_stat_uncert_plus",
+ "ialirtrates_stat_uncert_minus",
+ "num_acc_no_pha_stat_uncert_plus",
+ "num_acc_no_pha_stat_uncert_minus",
+ "coinrates_stat_uncert_plus",
+ "coinrates_stat_uncert_minus",
+ "penbgrates_stat_uncert_plus",
+ "penbgrates_stat_uncert_minus",
+ "nmulti_stat_uncert_plus",
+ "nmulti_stat_uncert_minus",
+ "nmultifix_stat_uncert_plus",
+ "nmultifix_stat_uncert_minus",
+ "nodd_stat_uncert_plus",
+ "nodd_stat_uncert_minus",
+ "num_reject_stat_uncert_plus",
+ "num_reject_stat_uncert_minus",
+ "nhazard_stat_uncert_plus",
+ "nhazard_stat_uncert_minus",
+ "nl4_stat_uncert_plus",
+ "nl4_stat_uncert_minus",
+ "npen_stat_uncert_plus",
+ "npen_stat_uncert_minus",
+ "sngrates_stat_uncert_plus",
+ "sngrates_stat_uncert_minus",
+ "num_haz_reject_stat_uncert_plus",
+ "num_haz_reject_stat_uncert_minus",
+ "nformat_stat_uncert_plus",
+ "nformat_stat_uncert_minus",
+ "l4fgrates_stat_uncert_plus",
+ "l4fgrates_stat_uncert_minus",
+ "num_trig_stat_uncert_plus",
+ "num_trig_stat_uncert_minus",
+ "nl2_stat_uncert_plus",
+ "nl2_stat_uncert_minus",
+ "l2bgrates_stat_uncert_plus",
+ "l2bgrates_stat_uncert_minus",
+ "penfgrates_stat_uncert_plus",
+ "penfgrates_stat_uncert_minus",
+ "nl3_stat_uncert_plus",
+ "nl3_stat_uncert_minus",
+ "nerror_stat_uncert_plus",
+ "nerror_stat_uncert_minus",
+ "l3fgrates_stat_uncert_plus",
+ "l3fgrates_stat_uncert_minus",
+ "num_acc_w_pha_stat_uncert_plus",
+ "num_acc_w_pha_stat_uncert_minus",
+ "naside_stat_uncert_plus",
+ "naside_stat_uncert_minus",
+ "l3bgrates_stat_uncert_plus",
+ "l3bgrates_stat_uncert_minus",
+ "num_haz_acc_w_pha_stat_uncert_plus",
+ "num_haz_acc_w_pha_stat_uncert_minus",
+ "nread_stat_uncert_plus",
+ "nread_stat_uncert_minus",
+ "pbufrates_stat_uncert_plus",
+ "pbufrates_stat_uncert_minus",
+ "nbadtags_stat_uncert_plus",
+ "nbadtags_stat_uncert_minus",
+ "l4bgrates_stat_uncert_plus",
+ "l4bgrates_stat_uncert_minus",
+ "nadcstim_stat_uncert_plus",
+ "nadcstim_stat_uncert_minus",
+ "nbadtraj_stat_uncert_plus",
+ "nbadtraj_stat_uncert_minus",
+ "num_haz_trig_stat_uncert_plus",
+ "num_haz_trig_stat_uncert_minus",
+ "sc_tick_by_frame",
+ ]
+
+ skip_sectored_vars = [
+ "sectorates",
+ "sectorates_stat_uncert_plus",
+ "sectorates_stat_uncert_minus",
+ "h_sectored_counts",
+ "h_energy_delta_minus",
+ "h_energy_delta_plus",
+ "he4_sectored_counts",
+ "he4_energy_delta_minus",
+ "he4_energy_delta_plus",
+ "cno_sectored_counts",
+ "cno_energy_delta_minus",
+ "cno_energy_delta_plus",
+ "nemgsi_sectored_counts",
+ "nemgsi_energy_delta_minus",
+ "nemgsi_energy_delta_plus",
+ "fe_sectored_counts",
+ "fe_energy_delta_minus",
+ "fe_energy_delta_plus",
+ "he4_sectored_counts_stat_uncert_plus",
+ "he4_sectored_counts_stat_uncert_minus",
+ "nemgsi_sectored_counts_stat_uncert_plus",
+ "nemgsi_sectored_counts_stat_uncert_minus",
+ "fe_sectored_counts_stat_uncert_plus",
+ "fe_sectored_counts_stat_uncert_minus",
+ "cno_sectored_counts_stat_uncert_plus",
+ "cno_sectored_counts_stat_uncert_minus",
+ "h_sectored_counts_stat_uncert_plus",
+ "h_sectored_counts_stat_uncert_minus",
+ "species",
+ ]
+
+ # Compare processed standard data to validation data skipping
+ # ccsds headers and sectored data vars
compare_data(
- expected_data=validation_data, actual_data=l1a_counts_data, skip=skip_fields
+ expected_data=validation_data,
+ actual_data=standard_counts_data,
+ skip=[*skip_vars, *skip_sectored_vars],
+ )
+
+ # Compare processed sectored data to validation data skipping
+ # ccsds headers and standard data vars
+ compare_data(
+ expected_data=sectored_validation_data,
+ actual_data=sectored_counts_data,
+ skip=[*skip_vars, *skip_standard_vars],
+ )
+
+ # Compare processed livetime data for sectored data to validation data
+ compare_data(
+ expected_data=livetime_validation_data,
+ actual_data=sectored_counts_data,
+ skip=[],
)
+@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.
Parameters
----------
- hk_packet_filepath : str
- Path to ccsds file for housekeeping data
- sci_packet_filepath : str
- Path to ccsds file for science data
+ hk_packet_filepath : Path
+ File path to ccsds file for housekeeping data
+ sci_packet_filepath : Path
+ File path to ccsds file for science data
"""
for packet_filepath in [hk_packet_filepath, sci_packet_filepath]:
- processed_datasets = hit_l1a(packet_filepath)
+ processed_datasets = hit_l1a(packet_filepath, packet_date="20100105")
assert isinstance(processed_datasets, list)
assert all(isinstance(ds, xr.Dataset) for ds in processed_datasets)
if packet_filepath == hk_packet_filepath:
assert len(processed_datasets) == 1
assert processed_datasets[0].attrs["Logical_source"] == "imap_hit_l1a_hk"
else:
- assert len(processed_datasets) == 2
+ assert len(processed_datasets) == 3
assert (
- processed_datasets[0].attrs["Logical_source"] == "imap_hit_l1a_counts"
+ processed_datasets[0].attrs["Logical_source"]
+ == "imap_hit_l1a_counts-standard"
)
assert (
processed_datasets[1].attrs["Logical_source"]
+ == "imap_hit_l1a_counts-sectored"
+ )
+ assert (
+ processed_datasets[2].attrs["Logical_source"]
== "imap_hit_l1a_direct-events"
)
+
+ # Assert that ValueError is raised when packet_date is None
+ with pytest.raises(
+ ValueError, match="Packet date is required for processing L1A data."
+ ):
+ hit_l1a(packet_filepath, "")
diff --git a/imap_processing/tests/hit/test_hit_l1b.py b/imap_processing/tests/hit/test_hit_l1b.py
index 8433925d01..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,10 +11,10 @@
SUMMED_PARTICLE_ENERGY_RANGE_MAPPING,
calculate_rates,
hit_l1b,
+ livetime_fraction_calculation,
process_sectored_rates_data,
process_standard_rates_data,
process_summed_rates_data,
- subset_data_for_sectored_counts,
sum_livetime_10min,
)
from imap_processing.tests.hit.helpers.l1_validation import (
@@ -28,7 +30,7 @@
def packet_filepath():
"""Set path to test data file"""
# TODO: Update this path when HIT provides a packet file with all apids.
- # Current test file only has the housekeeping apid is available.
+ # Current test file only has the housekeeping apid.
return (
imap_module_directory / "tests/hit/test_data/imap_hit_l0_raw_20100105_v001.pkts"
)
@@ -41,50 +43,55 @@ def sci_packet_filepath():
@pytest.fixture
-def dependencies(packet_filepath, sci_packet_filepath):
+def packet_date():
+ """Get the date of the packet file"""
+ return "20100105"
+
+
+@pytest.fixture
+def dependencies(packet_filepath, sci_packet_filepath, packet_date):
"""Get dependencies for L1B processing"""
- # Create dictionary of dependencies and add CCSDS packet file
- data_dict = {"imap_hit_l0_raw": packet_filepath}
- # Add L1A datasets
- l1a_datasets = hit_l1a.hit_l1a(packet_filepath)
- # TODO: Remove this when HIT provides a packet file with all apids.
- l1a_datasets.extend(hit_l1a.hit_l1a(sci_packet_filepath))
- for dataset in l1a_datasets:
- data_dict[dataset.attrs["Logical_source"]] = dataset
- return data_dict
+ # Get the L1A datasets from the housekeeping and science packet files
+ l1a_datasets = hit_l1a.hit_l1a(packet_filepath, packet_date) + hit_l1a.hit_l1a(
+ sci_packet_filepath, packet_date
+ )
+
+ return {
+ "hk": packet_filepath,
+ "standard-rates": next(
+ ds
+ for ds in l1a_datasets
+ if ds.attrs["Logical_source"] == "imap_hit_l1a_counts-standard"
+ ),
+ "summed-rates": next(
+ ds
+ for ds in l1a_datasets
+ if ds.attrs["Logical_source"] == "imap_hit_l1a_counts-standard"
+ ),
+ "sectored-rates": next(
+ ds
+ for ds in l1a_datasets
+ if ds.attrs["Logical_source"] == "imap_hit_l1a_counts-sectored"
+ ),
+ }
@pytest.fixture
def l1b_hk_dataset(dependencies):
"""Get the housekeeping dataset"""
- datasets = hit_l1b(dependencies)
- for dataset in datasets:
- if dataset.attrs["Logical_source"] == "imap_hit_l1b_hk":
- return dataset
+ return hit_l1b(dependencies["hk"], "hk")
+ # for dataset in datasets:
+ # if dataset.attrs["Logical_source"] == "imap_hit_l1b_hk":
+ # return dataset
@pytest.fixture
def l1b_standard_rates_dataset(dependencies):
"""Get the standard rates dataset"""
- datasets = hit_l1b(dependencies)
- for dataset in datasets:
- if dataset.attrs["Logical_source"] == "imap_hit_l1b_standard-rates":
- return dataset
-
-
-@pytest.fixture
-def l1a_counts_dataset(sci_packet_filepath):
- """Get L1A counts dataset to test l1b processing functions"""
- l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath)
- for dataset in l1a_datasets:
- if dataset.attrs["Logical_source"] == "imap_hit_l1a_counts":
- return dataset
-
-
-@pytest.fixture
-def livetime(l1a_counts_dataset: xr.Dataset) -> xr.DataArray:
- """Calculate livetime for L1A counts dataset"""
- return xr.DataArray(l1a_counts_dataset["livetime_counter"] / 270)
+ return hit_l1b(dependencies["standard-rates"], "standard-rates")
+ # for dataset in datasets:
+ # if dataset.attrs["Logical_source"] == "imap_hit_l1b_standard-rates":
+ # return dataset
def test_calculate_rates():
@@ -148,120 +155,12 @@ def test_sum_livetime_10min():
xr.testing.assert_equal(result, expected_livetime)
-def test_subset_data_for_sectored_counts():
- """Test the subset_data_for_sectored_counts function."""
-
- def create_l1a_counts_dataset(hdr_minute_cnt_values):
- """Helper to create L1A counts dataset."""
- return xr.Dataset(
- {
- "hdr_minute_cnt": ("epoch", hdr_minute_cnt_values),
- "h_sectored_counts": ("epoch", np.arange(len(hdr_minute_cnt_values))),
- "he4_sectored_counts": ("epoch", np.arange(len(hdr_minute_cnt_values))),
- },
- )
-
- def validate_subset(l1a_counts_dataset, livetime):
- """Helper to validate the subset results."""
- subset_dataset, subset_livetime = subset_data_for_sectored_counts(
- l1a_counts_dataset, livetime
- )
- assert subset_dataset.sizes["epoch"] == 10
- assert len(subset_livetime["epoch"]) == 10
- assert np.all(subset_dataset["hdr_minute_cnt"].values % 10 == np.arange(10))
-
- # Create a sample livetime data array
- livetime = xr.DataArray(np.arange(1.0, 31.0, dtype=np.float32), dims=["epoch"])
-
- # Test with partial data at the start and end of the dataset
- l1a_counts_dataset = create_l1a_counts_dataset(np.arange(105, 135))
- validate_subset(l1a_counts_dataset, livetime)
-
- # Test with partial data in the middle of the dataset
- l1a_counts_dataset = create_l1a_counts_dataset(
- [
- 100,
- 101,
- 102,
- 103,
- 104,
- 105,
- 106,
- 107,
- 108,
- 109,
- 110,
- 111,
- 112,
- 113,
- 114,
- 120,
- 121,
- 122,
- 123,
- 124,
- 130,
- 131,
- 132,
- 133,
- 134,
- 135,
- 136,
- 137,
- 138,
- 139,
- ]
- )
- validate_subset(l1a_counts_dataset, livetime)
-
- # Test with partial data at the start, middle, and end of the dataset
- l1a_counts_dataset = create_l1a_counts_dataset(
- [
- 105,
- 106,
- 107,
- 108,
- 109,
- 110,
- 111,
- 112,
- 113,
- 114,
- 115,
- 116,
- 117,
- 118,
- 119,
- 120,
- 121,
- 122,
- 130,
- 131,
- 132,
- 133,
- 134,
- 135,
- 136,
- 137,
- 138,
- 139,
- 140,
- 141,
- ]
- )
- validate_subset(l1a_counts_dataset, livetime)
-
- # Test with only partial data in the dataset
- l1a_counts_dataset = create_l1a_counts_dataset(np.arange(100, 160, 2))
- with pytest.raises(
- ValueError, match="No valid start indices found for complete sectored counts."
- ):
- subset_data_for_sectored_counts(l1a_counts_dataset, livetime)
-
-
-def test_process_summed_rates_data(l1a_counts_dataset, 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"""
+ l1a_counts_dataset = dependencies["summed-rates"]
+ livetime = xr.DataArray(l1a_counts_dataset["livetime_counter"] / 270)
l1b_summed_rates_dataset = process_summed_rates_data(l1a_counts_dataset, livetime)
# Check that a xarray dataset is returned
@@ -301,8 +200,12 @@ def test_process_summed_rates_data(l1a_counts_dataset, livetime):
assert f"{particle}_energy_delta_plus" in l1b_summed_rates_dataset.data_vars
-def test_process_standard_rates_data(l1a_counts_dataset, livetime):
+@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"""
+
+ l1a_counts_dataset = dependencies["standard-rates"]
+ livetime = xr.DataArray(l1a_counts_dataset["livetime_counter"] / 270)
l1b_standard_rates_dataset = process_standard_rates_data(
l1a_counts_dataset, livetime
)
@@ -390,9 +293,12 @@ def test_process_standard_rates_data(l1a_counts_dataset, livetime):
)
-def test_process_sectored_rates_data(l1a_counts_dataset, livetime):
+@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"""
+ l1a_counts_dataset = dependencies["sectored-rates"]
+ livetime = xr.DataArray(l1a_counts_dataset["livetime_counter"] / 270)
l1b_sectored_rates_dataset = process_sectored_rates_data(
l1a_counts_dataset, livetime
)
@@ -435,6 +341,7 @@ def test_process_sectored_rates_data(l1a_counts_dataset, livetime):
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
@@ -522,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.
@@ -611,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"
@@ -650,30 +594,42 @@ def test_hit_l1b_missing_apid(sci_packet_filepath):
Science CCSDS packet file path. Only contains science APID and is
missing the housekeeping APID.
"""
- # Create a dependency dictionary with a science CCSDS packet file
- # excluding the housekeeping apid
- dependency = {"imap_hit_l0_raw": sci_packet_filepath}
- datasets = hit_l1b(dependency)
- assert len(datasets) == 0
+ dataset = hit_l1b(sci_packet_filepath, "hk")
+ assert dataset is None
-def test_hit_l1b(dependencies):
- """Test creating L1B CDF files
+def test_hit_l1b_unsupported_descriptor():
+ # Arrange
+ dependency = xr.Dataset() # Mock dependency
+ unsupported_descriptor = "invalid-descriptor"
- Creates a list of xarray datasets for each L1B product
+ with pytest.raises(
+ ValueError, match=f"Unsupported descriptor: {unsupported_descriptor}"
+ ):
+ hit_l1b(dependency, unsupported_descriptor)
+
+
+@pytest.mark.parametrize(
+ "dependency_key, expected_logical_source",
+ [
+ ("hk", "imap_hit_l1b_hk"),
+ ("standard-rates", "imap_hit_l1b_standard-rates"),
+ ("summed-rates", "imap_hit_l1b_summed-rates"),
+ ("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
Parameters
----------
dependencies : dict
- Dictionary of L1A datasets and CCSDS packet file path
+ Dictionary of L1B products and their dependencies.
"""
- # TODO: update assertions after science data processing is completed
- datasets = hit_l1b(dependencies)
-
- assert len(datasets) == 4
- for dataset in datasets:
- assert isinstance(dataset, xr.Dataset)
- assert datasets[0].attrs["Logical_source"] == "imap_hit_l1b_hk"
- assert datasets[1].attrs["Logical_source"] == "imap_hit_l1b_standard-rates"
- assert datasets[2].attrs["Logical_source"] == "imap_hit_l1b_summed-rates"
- assert datasets[3].attrs["Logical_source"] == "imap_hit_l1b_sectored-rates"
+ # Check that the dataset is created and has the correct logical source
+ dependency = dependencies.get(dependency_key)
+ l1b_descriptor = dependency_key
+ dataset = hit_l1b(dependency, l1b_descriptor)
+ assert isinstance(dataset, xr.Dataset)
+ assert dataset.attrs["Logical_source"] == expected_logical_source
diff --git a/imap_processing/tests/hit/test_hit_l2.py b/imap_processing/tests/hit/test_hit_l2.py
index 92158ba873..0a1039bd9f 100644
--- a/imap_processing/tests/hit/test_hit_l2.py
+++ b/imap_processing/tests/hit/test_hit_l2.py
@@ -42,19 +42,33 @@ def sci_packet_filepath():
@pytest.fixture
-def dependencies(sci_packet_filepath):
+def packet_date():
+ """Get the date of the packet file"""
+ return "20100105"
+
+
+@pytest.fixture
+def dependencies(sci_packet_filepath, packet_date):
"""Get dependencies for L2 processing"""
# Create dictionary of dependencies
- data_dict = {}
- l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath)
- for l1a_dataset in l1a_datasets:
- l1a_data_dict = {}
- if l1a_dataset.attrs["Logical_source"] == "imap_hit_l1a_counts":
- l1a_data_dict["imap_hit_l1a_counts"] = l1a_dataset
- l1b_datasets = hit_l1b(l1a_data_dict)
- for l1b_dataset in l1b_datasets:
- data_dict[l1b_dataset.attrs["Logical_source"]] = l1b_dataset
- return data_dict
+ dependencies = {}
+
+ # Get L1A datasets
+ l1a_datasets = hit_l1a.hit_l1a(sci_packet_filepath, packet_date)
+
+ # Get L1B datasets from L1A datasets
+ for dataset in l1a_datasets:
+ if dataset.attrs["Logical_source"] == "imap_hit_l1a_counts-standard":
+ # Standard and summed rates datasets are created from the same L1A dataset
+ dependencies["imap_hit_l1b_standard-rates"] = hit_l1b(
+ dataset, "standard-rates"
+ )
+ dependencies["imap_hit_l1b_summed-rates"] = hit_l1b(dataset, "summed-rates")
+ elif dataset.attrs["Logical_source"] == "imap_hit_l1a_counts-sectored":
+ dependencies["imap_hit_l1b_sectored-rates"] = hit_l1b(
+ dataset, "sectored-rates"
+ )
+ return dependencies
@pytest.fixture
@@ -673,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
):
@@ -833,8 +848,27 @@ def test_process_standard_intensity(l1b_standard_rates_dataset, ancillary_depend
)
-def test_hit_l2(dependencies, ancillary_dependencies):
- """Test creating L2 datasets ready for CDF output
+@pytest.mark.parametrize(
+ "dataset_key, ancillary_key, expected_logical_source",
+ [
+ ("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),
+ ),
+ ],
+)
+def test_hit_l2(
+ dependencies,
+ ancillary_dependencies,
+ dataset_key,
+ ancillary_key,
+ expected_logical_source,
+):
+ """Test creating L2 datasets ready for CDF output.
Creates a list of xarray datasets for L2 products.
@@ -846,21 +880,8 @@ def test_hit_l2(dependencies, ancillary_dependencies):
ancillary_dependencies : dict
Dictionary of ancillary file paths
"""
- l2_datasets = hit_l2(
- dependencies["imap_hit_l1b_summed-rates"], ancillary_dependencies["summed"]
- )
- assert len(l2_datasets) == 1
- assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_summed-intensity"
-
- l2_datasets = hit_l2(
- dependencies["imap_hit_l1b_standard-rates"], ancillary_dependencies["standard"]
- )
- assert len(l2_datasets) == 1
- assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_standard-intensity"
- l2_datasets = hit_l2(
- dependencies["imap_hit_l1b_sectored-rates"],
- ancillary_dependencies["macropixel"],
+ l2_dataset = hit_l2(
+ dependencies[dataset_key], ancillary_dependencies[ancillary_key]
)
- assert len(l2_datasets) == 1
- assert l2_datasets[0].attrs["Logical_source"] == "imap_hit_l2_macropixel-intensity"
+ assert l2_dataset.attrs["Logical_source"] == expected_logical_source
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-212T16_55_27.531613 b/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2025-212T16_55_27.531613
new file mode 100644
index 0000000000..a92819022f
--- /dev/null
+++ b/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2025-212T16_55_27.531613
@@ -0,0 +1,115 @@
+
+
+
+Thu Jul 31 16:32:38 UTC 2025
+2025/212-16:32:38.239 /app/iois version: iois_1.5, multi-mission OIS version: ois_1.58
+2025/212-16:32:38.240 hostname = ip-10-0-179-228.us-west-2.compute.internal
+2025/212-16:32:38.241 Reading config file: /app/iois_1_config.txt, qualifier: IOIS
+2025/212-16:32:38.242 lock file from I-OIS config file is: /tmp/imap_iois_1_lockfile
+2025/212-16:32:38.242 Opened composite raw record file with frame headers only: iois_1_raw_record_composite_with_headers_only_2025_212_16_32_38.partial
+2025/212-16:32:38.242 Opened packets file for SDC: iois_1_packets_2025_212_16_32_38.partial
+2025/212-16:32:38.242 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_212_16_32_38.partial
+2025/212-16:32:38.242 Opened raw record file for Korea antenna_partner: IOIS_1_raw_record_21_2025_212_16_32_38.partial
+2025/212-16:33:03.247 EnableTCPKeepAlives: TCP_KEEPINTVL=180, TCP_KEEPCNT=3, TCP_KEEPIDLE=20 for Kiel antenna partner connection
+2025/212-16:33:03.247 Kiel antenna partner connection is up.
+2025/212-16:33:04.063 Error: dropout in VCDU counter for VCID=5! previous: 148, current: 150
+2025/212-16:33:06.070 Error: dropout in VCDU counter for VCID=5! previous: 155, current: 157
+2025/212-16:33:07.074 Error: dropout in VCDU counter for VCID=5! previous: 163, current: 165
+2025/212-16:33:09.078 Error: dropout in VCDU counter for VCID=5! previous: 171, current: 173
+2025/212-16:33:10.079 Error: dropout in VCDU counter for VCID=5! previous: 179, current: 181
+2025/212-16:33:12.090 Error: dropout in VCDU counter for VCID=5! previous: 187, current: 189
+2025/212-16:33:13.103 Error: dropout in VCDU counter for VCID=5! previous: 195, current: 197
+2025/212-16:33:15.099 Error: dropout in VCDU counter for VCID=5! previous: 203, current: 205
+2025/212-16:33:17.110 Error: dropout in VCDU counter for VCID=5! previous: 211, current: 213
+2025/212-16:33:18.114 Error: dropout in VCDU counter for VCID=5! previous: 219, current: 221
+2025/212-16:33:20.118 Error: dropout in VCDU counter for VCID=5! previous: 227, current: 229
+2025/212-16:33:21.126 Error: dropout in VCDU counter for VCID=5! previous: 235, current: 237
+2025/212-16:33:23.134 Error: dropout in VCDU counter for VCID=5! previous: 243, current: 245
+2025/212-16:33:24.138 Error: dropout in VCDU counter for VCID=5! previous: 250, current: 252
+2025/212-16:33:26.142 Error: dropout in VCDU counter for VCID=5! previous: 2, current: 4
+2025/212-16:33:27.147 Error: dropout in VCDU counter for VCID=5! previous: 10, current: 12
+2025/212-16:33:29.150 Error: dropout in VCDU counter for VCID=5! previous: 18, current: 20
+2025/212-16:33:30.154 Error: dropout in VCDU counter for VCID=5! previous: 26, current: 28
+2025/212-16:33:32.163 Error: dropout in VCDU counter for VCID=5! previous: 34, current: 36
+2025/212-16:33:33.166 Error: dropout in VCDU counter for VCID=5! previous: 42, current: 44
+2025/212-16:33:35.174 Error: dropout in VCDU counter for VCID=5! previous: 50, current: 52
+2025/212-16:33:37.183 Error: dropout in VCDU counter for VCID=5! previous: 58, current: 60
+2025/212-16:33:38.187 Error: dropout in VCDU counter for VCID=5! previous: 66, current: 68
+2025/212-16:33:39.185 Closed packets file for SDC: iois_1_packets_2025_212_16_32_38.partial
+2025/212-16:33:39.186 Renamed iois_1_packets_2025_212_16_32_38.partial to iois_1_packets_2025_212_16_32_38.
+2025/212-16:33:39.186 Spawning: cp
+2025/212-16:33:39.187 Opened packets file for SDC: iois_1_packets_2025_212_16_33_39.partial
+2025/212-16:33:40.189 Kiel antenna partner connection is down!
+2025/212-16:33:40.189 Spawned command succeeded: cp
+2025/212-16:34:40.199 Closed packets file for SDC: iois_1_packets_2025_212_16_33_39.partial
+2025/212-16:34:40.199 Renamed iois_1_packets_2025_212_16_33_39.partial to iois_1_packets_2025_212_16_33_39.
+2025/212-16:34:40.199 Spawning: cp
+2025/212-16:34:40.200 Opened packets file for SDC: iois_1_packets_2025_212_16_34_40.partial
+2025/212-16:34:41.200 Spawned command succeeded: cp
+2025/212-16:35:41.211 Deleting zero-length file: iois_1_packets_2025_212_16_34_40.partial
+2025/212-16:35:41.211 Opened packets file for SDC: iois_1_packets_2025_212_16_35_41.partial
+2025/212-16:36:00.214 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_212_16_32_38.partial
+2025/212-16:36:00.215 Renamed IOIS_1_raw_record_20_2025_212_16_32_38.partial to IOIS_1_raw_record_20_2025_212_16_32_38.
+2025/212-16:36:00.215 Spawning: rsync
+2025/212-16:36:00.215 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_212_16_36_00.partial
+2025/212-16:36:00.215 Deleting zero-length file: IOIS_1_raw_record_21_2025_212_16_32_38.partial
+2025/212-16:36:00.215 Opened raw record file for Korea antenna_partner: IOIS_1_raw_record_21_2025_212_16_36_00.partial
+2025/212-16:36:03.216 Spawned command succeeded: rsync
+2025/212-16:36:42.223 Deleting zero-length file: iois_1_packets_2025_212_16_35_41.partial
+2025/212-16:36:42.223 Opened packets file for SDC: iois_1_packets_2025_212_16_36_42.partial
+2025/212-16:37:43.233 Deleting zero-length file: iois_1_packets_2025_212_16_36_42.partial
+2025/212-16:37:43.233 Opened packets file for SDC: iois_1_packets_2025_212_16_37_43.partial
+2025/212-16:38:44.244 Deleting zero-length file: iois_1_packets_2025_212_16_37_43.partial
+2025/212-16:38:44.245 Opened packets file for SDC: iois_1_packets_2025_212_16_38_44.partial
+2025/212-16:39:45.259 Deleting zero-length file: iois_1_packets_2025_212_16_38_44.partial
+2025/212-16:39:45.259 Opened packets file for SDC: iois_1_packets_2025_212_16_39_45.partial
+2025/212-16:40:46.269 Deleting zero-length file: iois_1_packets_2025_212_16_39_45.partial
+2025/212-16:40:46.269 Opened packets file for SDC: iois_1_packets_2025_212_16_40_46.partial
+2025/212-16:41:00.272 Deleting zero-length file: IOIS_1_raw_record_20_2025_212_16_36_00.partial
+2025/212-16:41:00.272 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_212_16_41_00.partial
+2025/212-16:41:00.272 Deleting zero-length file: IOIS_1_raw_record_21_2025_212_16_36_00.partial
+2025/212-16:41:00.272 Opened raw record file for Korea antenna_partner: IOIS_1_raw_record_21_2025_212_16_41_00.partial
+2025/212-16:41:47.280 Deleting zero-length file: iois_1_packets_2025_212_16_40_46.partial
+2025/212-16:41:47.280 Opened packets file for SDC: iois_1_packets_2025_212_16_41_47.partial
+2025/212-16:42:48.290 Deleting zero-length file: iois_1_packets_2025_212_16_41_47.partial
+2025/212-16:42:48.291 Opened packets file for SDC: iois_1_packets_2025_212_16_42_48.partial
+2025/212-16:43:49.300 Deleting zero-length file: iois_1_packets_2025_212_16_42_48.partial
+2025/212-16:43:49.301 Opened packets file for SDC: iois_1_packets_2025_212_16_43_49.partial
+2025/212-16:44:50.311 Deleting zero-length file: iois_1_packets_2025_212_16_43_49.partial
+2025/212-16:44:50.311 Opened packets file for SDC: iois_1_packets_2025_212_16_44_50.partial
+2025/212-16:45:51.321 Deleting zero-length file: iois_1_packets_2025_212_16_44_50.partial
+2025/212-16:45:51.321 Opened packets file for SDC: iois_1_packets_2025_212_16_45_51.partial
+2025/212-16:46:00.323 Deleting zero-length file: IOIS_1_raw_record_20_2025_212_16_41_00.partial
+2025/212-16:46:00.323 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_212_16_46_00.partial
+2025/212-16:46:00.323 Deleting zero-length file: IOIS_1_raw_record_21_2025_212_16_41_00.partial
+2025/212-16:46:00.323 Opened raw record file for Korea antenna_partner: IOIS_1_raw_record_21_2025_212_16_46_00.partial
+2025/212-16:46:52.332 Deleting zero-length file: iois_1_packets_2025_212_16_45_51.partial
+2025/212-16:46:52.332 Opened packets file for SDC: iois_1_packets_2025_212_16_46_52.partial
+2025/212-16:47:53.342 Deleting zero-length file: iois_1_packets_2025_212_16_46_52.partial
+2025/212-16:47:53.342 Opened packets file for SDC: iois_1_packets_2025_212_16_47_53.partial
+2025/212-16:48:54.353 Deleting zero-length file: iois_1_packets_2025_212_16_47_53.partial
+2025/212-16:48:54.353 Opened packets file for SDC: iois_1_packets_2025_212_16_48_54.partial
+2025/212-16:49:55.363 Deleting zero-length file: iois_1_packets_2025_212_16_48_54.partial
+2025/212-16:49:55.363 Opened packets file for SDC: iois_1_packets_2025_212_16_49_55.partial
+2025/212-16:50:56.373 Deleting zero-length file: iois_1_packets_2025_212_16_49_55.partial
+2025/212-16:50:56.374 Opened packets file for SDC: iois_1_packets_2025_212_16_50_56.partial
+2025/212-16:51:00.374 Deleting zero-length file: IOIS_1_raw_record_20_2025_212_16_46_00.partial
+2025/212-16:51:00.374 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_212_16_51_00.partial
+2025/212-16:51:00.374 Deleting zero-length file: IOIS_1_raw_record_21_2025_212_16_46_00.partial
+2025/212-16:51:00.374 Opened raw record file for Korea antenna_partner: IOIS_1_raw_record_21_2025_212_16_51_00.partial
+2025/212-16:51:57.384 Deleting zero-length file: iois_1_packets_2025_212_16_50_56.partial
+2025/212-16:51:57.384 Opened packets file for SDC: iois_1_packets_2025_212_16_51_57.partial
+2025/212-16:52:58.394 Deleting zero-length file: iois_1_packets_2025_212_16_51_57.partial
+2025/212-16:52:58.394 Opened packets file for SDC: iois_1_packets_2025_212_16_52_58.partial
+2025/212-16:53:59.405 Deleting zero-length file: iois_1_packets_2025_212_16_52_58.partial
+2025/212-16:53:59.405 Opened packets file for SDC: iois_1_packets_2025_212_16_53_59.partial
+2025/212-16:55:00.415 Deleting zero-length file: iois_1_packets_2025_212_16_53_59.partial
+2025/212-16:55:00.415 Opened packets file for SDC: iois_1_packets_2025_212_16_55_00.partial
+2025/212-16:55:27.152 Closed composite raw record file with frame headers only: iois_1_raw_record_composite_with_headers_only_2025_212_16_32_38.partial
+2025/212-16:55:27.152 Renamed iois_1_raw_record_composite_with_headers_only_2025_212_16_32_38.partial to iois_1_raw_record_composite_with_headers_only_2025_212_16_32_38.
+2025/212-16:55:27.152 Spawning: mv
+2025/212-16:55:27.152 Deleting zero-length file: iois_1_packets_2025_212_16_55_00.partial
+2025/212-16:55:27.152 Deleting zero-length file: IOIS_1_raw_record_20_2025_212_16_51_00.partial
+2025/212-16:55:27.152 Deleting zero-length file: IOIS_1_raw_record_21_2025_212_16_51_00.partial
+2025/212-16:55:27.153 SIGKILLHandler: deleting lock file /tmp/imap_iois_1_lockfile.
+2025/212-16:55:27.153 SIGKILLHandler: Exiting iois...
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/test_data/ialirt_test_data.csv b/imap_processing/tests/ialirt/data/l0/ialirt_test_data.csv
similarity index 100%
rename from imap_processing/tests/ialirt/test_data/ialirt_test_data.csv
rename to imap_processing/tests/ialirt/data/l0/ialirt_test_data.csv
diff --git a/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_400_n_sw_6.0_T_sw_80000_v2.csv b/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_400_n_sw_6.0_T_sw_80000_v2.csv
new file mode 100644
index 0000000000..1a088571a3
--- /dev/null
+++ b/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_400_n_sw_6.0_T_sw_80000_v2.csv
@@ -0,0 +1,73 @@
+Energy [eV/q],Count Rates [Hz],Count Rates Error [Hz]
+19098.357902,296286.826,1331.981
+19098.357902,0.000,0.000
+17541.176889,0.000,0.000
+16113.177329,0.000,0.000
+14798.379984,0.000,0.000
+13591.365778,0.000,0.000
+12485.777044,0.000,0.000
+11467.618290,0.000,0.000
+10532.608216,0.000,0.000
+9675.514168,0.000,0.000
+8885.046380,0.000,0.000
+8165.393845,0.000,0.000
+7501.760233,0.000,0.000
+6888.477149,0.000,0.000
+6327.926581,29.632,13.320
+5811.486083,0.000,0.000
+5338.867546,29.632,13.320
+4901.303180,0.000,0.000
+4504.298870,0.000,0.000
+4138.382520,0.000,0.000
+3800.760624,0.000,0.000
+3490.866227,0.000,0.000
+3205.462334,0.000,0.000
+2944.699516,0.000,0.000
+2705.519228,0.000,0.000
+2485.023495,0.000,0.000
+2281.728846,29.632,13.320
+2094.335628,29.632,13.320
+1921.410538,0.000,0.000
+1764.614440,148.158,29.785
+1621.075258,118.527,26.641
+1489.379616,118.527,26.641
+1369.255230,59.263,18.838
+1257.562068,29.632,13.320
+1155.043150,266.685,39.961
+1061.325411,1511.214,95.127
+974.875126,4415.115,162.597
+895.314188,6044.856,190.254
+822.018852,8178.334,221.296
+754.982368,5511.486,181.667
+693.547324,2874.270,131.191
+636.793361,1126.003,82.113
+584.819780,622.265,61.042
+537.016673,29.632,13.320
+493.208286,59.263,18.838
+453.103315,0.000,0.000
+416.133867,0.000,0.000
+382.037059,0.000,0.000
+350.921008,0.000,0.000
+322.396008,0.000,0.000
+296.176976,0.000,0.000
+271.952917,0.000,0.000
+249.936708,0.000,0.000
+229.494886,0.000,0.000
+210.757138,0.000,0.000
+193.581931,29.632,13.320
+177.766309,0.000,0.000
+163.295895,0.000,0.000
+150.015166,0.000,0.000
+137.803904,0.000,0.000
+126.579577,0.000,0.000
+116.253172,0.000,0.000
+106.797953,0.000,0.000
+895.314188,0.000,0.000
+876.436861,0.000,0.000
+857.957554,0.000,0.000
+839.867876,0.000,0.000
+822.159611,0.000,0.000
+804.824717,0.000,0.000
+787.855323,0.000,0.000
+771.243721,0.000,0.000
+754.982368,0.000,0.000
diff --git a/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_550_n_sw_5_T_sw_100000_v2.csv b/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_550_n_sw_5_T_sw_100000_v2.csv
new file mode 100644
index 0000000000..f86cfe557e
--- /dev/null
+++ b/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_550_n_sw_5_T_sw_100000_v2.csv
@@ -0,0 +1,73 @@
+Energy [eV/q],Count Rates [Hz],Count Rates Error [Hz]
+19098.357902,296286.826,1331.981
+19098.357902,0.000,0.000
+17541.176889,0.000,0.000
+16113.177329,29.632,13.320
+14798.379984,0.000,0.000
+13591.365778,0.000,0.000
+12485.777044,0.000,0.000
+11467.618290,0.000,0.000
+10532.608216,0.000,0.000
+9675.514168,0.000,0.000
+8885.046380,0.000,0.000
+8165.393845,29.632,13.320
+7501.760233,0.000,0.000
+6888.477149,0.000,0.000
+6327.926581,0.000,0.000
+5811.486083,0.000,0.000
+5338.867546,0.000,0.000
+4901.303180,0.000,0.000
+4504.298870,0.000,0.000
+4138.382520,0.000,0.000
+3800.760624,0.000,0.000
+3490.866227,88.895,23.072
+3205.462334,177.790,32.628
+2944.699516,266.685,39.961
+2705.519228,59.263,18.838
+2485.023495,29.632,13.320
+2281.728846,0.000,0.000
+2094.335628,118.527,26.641
+1921.410538,1303.792,88.358
+1764.614440,4504.010,164.226
+1621.075258,6133.751,191.648
+1489.379616,5600.381,183.126
+1369.255230,3170.586,137.788
+1257.562068,948.213,75.352
+1155.043150,207.422,35.243
+1061.325411,29.632,13.320
+974.875126,0.000,0.000
+895.314188,0.000,0.000
+822.018852,0.000,0.000
+754.982368,0.000,0.000
+693.547324,0.000,0.000
+636.793361,0.000,0.000
+584.819780,0.000,0.000
+537.016673,0.000,0.000
+493.208286,0.000,0.000
+453.103315,0.000,0.000
+416.133867,0.000,0.000
+382.037059,0.000,0.000
+350.921008,0.000,0.000
+322.396008,0.000,0.000
+296.176976,0.000,0.000
+271.952917,0.000,0.000
+249.936708,0.000,0.000
+229.494886,0.000,0.000
+210.757138,0.000,0.000
+193.581931,0.000,0.000
+177.766309,0.000,0.000
+163.295895,0.000,0.000
+150.015166,0.000,0.000
+137.803904,0.000,0.000
+126.579577,0.000,0.000
+116.253172,0.000,0.000
+106.797953,0.000,0.000
+1764.614440,0.000,0.000
+1727.604298,0.000,0.000
+1691.370389,0.000,0.000
+1655.896431,0.000,0.000
+1621.166486,0.000,0.000
+1587.164950,0.000,0.000
+1553.876545,0.000,0.000
+1521.286315,0.000,0.000
+1489.379616,0.000,0.000
diff --git a/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_650_n_sw_3.0_T_sw_120000_v2.csv b/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_650_n_sw_3.0_T_sw_120000_v2.csv
new file mode 100644
index 0000000000..4347d77ef6
--- /dev/null
+++ b/imap_processing/tests/ialirt/data/l0/ialirt_test_data_u_sw_650_n_sw_3.0_T_sw_120000_v2.csv
@@ -0,0 +1,73 @@
+Energy [eV/q],Count Rates [Hz],Count Rates Error [Hz]
+19098.357902,296286.826,1331.981
+19098.357902,0.000,0.000
+17541.176889,0.000,0.000
+16113.177329,0.000,0.000
+14798.379984,0.000,0.000
+13591.365778,0.000,0.000
+12485.777044,0.000,0.000
+11467.618290,0.000,0.000
+10532.608216,0.000,0.000
+9675.514168,0.000,0.000
+8885.046380,0.000,0.000
+8165.393845,29.632,13.320
+7501.760233,0.000,0.000
+6888.477149,0.000,0.000
+6327.926581,29.632,13.320
+5811.486083,0.000,0.000
+5338.867546,0.000,0.000
+4901.303180,88.895,23.072
+4504.298870,118.527,26.641
+4138.382520,148.158,29.785
+3800.760624,0.000,0.000
+3490.866227,0.000,0.000
+3205.462334,0.000,0.000
+2944.699516,88.895,23.072
+2705.519228,563.001,58.063
+2485.023495,2044.584,110.648
+2281.728846,4118.799,157.046
+2094.335628,3200.218,138.430
+1921.410538,1926.057,107.393
+1764.614440,622.265,61.042
+1621.075258,29.632,13.320
+1489.379616,29.632,13.320
+1369.255230,0.000,0.000
+1257.562068,0.000,0.000
+1155.043150,0.000,0.000
+1061.325411,0.000,0.000
+974.875126,0.000,0.000
+895.314188,0.000,0.000
+822.018852,0.000,0.000
+754.982368,0.000,0.000
+693.547324,0.000,0.000
+636.793361,0.000,0.000
+584.819780,0.000,0.000
+537.016673,0.000,0.000
+493.208286,0.000,0.000
+453.103315,0.000,0.000
+416.133867,0.000,0.000
+382.037059,0.000,0.000
+350.921008,0.000,0.000
+322.396008,0.000,0.000
+296.176976,0.000,0.000
+271.952917,0.000,0.000
+249.936708,0.000,0.000
+229.494886,0.000,0.000
+210.757138,0.000,0.000
+193.581931,29.632,13.320
+177.766309,0.000,0.000
+163.295895,0.000,0.000
+150.015166,0.000,0.000
+137.803904,0.000,0.000
+126.579577,0.000,0.000
+116.253172,0.000,0.000
+106.797953,0.000,0.000
+2485.023495,0.000,0.000
+2432.455881,0.000,0.000
+2381.000269,0.000,0.000
+2330.633139,0.000,0.000
+2281.331462,0.000,0.000
+2233.072702,0.000,0.000
+2185.834797,0.000,0.000
+2139.596152,0.000,0.000
+2094.335628,0.000,0.000
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/data/l0/swapi_ialirt_energy_steps.csv b/imap_processing/tests/ialirt/data/l0/swapi_ialirt_energy_steps.csv
new file mode 100644
index 0000000000..66ad1f1711
--- /dev/null
+++ b/imap_processing/tests/ialirt/data/l0/swapi_ialirt_energy_steps.csv
@@ -0,0 +1,145 @@
+ο»Ώtimestamp,Sweep #,ESA Step #,Energy
+5/19/2025 0:00,2,0,19098.3579
+5/19/2025 0:00,2,1,19098.3579
+5/19/2025 0:00,2,2,17541.17689
+5/19/2025 0:00,2,3,16113.17733
+5/19/2025 0:00,2,4,14798.37998
+5/19/2025 0:00,2,5,13591.36578
+5/19/2025 0:00,2,6,12485.77704
+5/19/2025 0:00,2,7,11467.61829
+5/19/2025 0:00,2,8,10532.60822
+5/19/2025 0:00,2,9,9675.514168
+5/19/2025 0:00,2,10,8885.04638
+5/19/2025 0:00,2,11,8165.393845
+5/19/2025 0:00,2,12,7501.760233
+5/19/2025 0:00,2,13,6888.477149
+5/19/2025 0:00,2,14,6327.926581
+5/19/2025 0:00,2,15,5811.486083
+5/19/2025 0:00,2,16,5338.867546
+5/19/2025 0:00,2,17,4901.30318
+5/19/2025 0:00,2,18,4504.29887
+5/19/2025 0:00,2,19,4138.38252
+5/19/2025 0:00,2,20,3800.760624
+5/19/2025 0:00,2,21,3490.866227
+5/19/2025 0:00,2,22,3205.462334
+5/19/2025 0:00,2,23,2944.699516
+5/19/2025 0:00,2,24,2705.519228
+5/19/2025 0:00,2,25,2485.023495
+5/19/2025 0:00,2,26,2281.728846
+5/19/2025 0:00,2,27,2094.335628
+5/19/2025 0:00,2,28,1921.410538
+5/19/2025 0:00,2,29,1764.61444
+5/19/2025 0:00,2,30,1621.075258
+5/19/2025 0:00,2,31,1489.379616
+5/19/2025 0:00,2,32,1369.25523
+5/19/2025 0:00,2,33,1257.562068
+5/19/2025 0:00,2,34,1155.04315
+5/19/2025 0:00,2,35,1061.325411
+5/19/2025 0:00,2,36,974.875126
+5/19/2025 0:00,2,37,895.314188
+5/19/2025 0:00,2,38,822.018852
+5/19/2025 0:00,2,39,754.982368
+5/19/2025 0:00,2,40,693.547324
+5/19/2025 0:00,2,41,636.793361
+5/19/2025 0:00,2,42,584.81978
+5/19/2025 0:00,2,43,537.016673
+5/19/2025 0:00,2,44,493.208286
+5/19/2025 0:00,2,45,453.103315
+5/19/2025 0:00,2,46,416.133867
+5/19/2025 0:00,2,47,382.037059
+5/19/2025 0:00,2,48,350.921008
+5/19/2025 0:00,2,49,322.396008
+5/19/2025 0:00,2,50,296.176976
+5/19/2025 0:00,2,51,271.952917
+5/19/2025 0:00,2,52,249.936708
+5/19/2025 0:00,2,53,229.494886
+5/19/2025 0:00,2,54,210.757138
+5/19/2025 0:00,2,55,193.581931
+5/19/2025 0:00,2,56,177.766309
+5/19/2025 0:00,2,57,163.295895
+5/19/2025 0:00,2,58,150.015166
+5/19/2025 0:00,2,59,137.803904
+5/19/2025 0:00,2,60,126.579577
+5/19/2025 0:00,2,61,116.253172
+5/19/2025 0:00,2,62,106.797953
+5/19/2025 0:00,2,63,2485.023495
+5/19/2025 0:00,2,64,2432.455881
+5/19/2025 0:00,2,65,2381.000269
+5/19/2025 0:00,2,66,2330.633139
+5/19/2025 0:00,2,67,2281.331462
+5/19/2025 0:00,2,68,2233.072702
+5/19/2025 0:00,2,69,2185.834797
+5/19/2025 0:00,2,70,2139.596152
+5/19/2025 0:00,2,71,2094.335628
+5/19/2025 0:00,1,0,0
+5/19/2025 0:00,1,1,0
+5/19/2025 0:00,1,2,0
+5/19/2025 0:00,1,3,0
+5/19/2025 0:00,1,4,0
+5/19/2025 0:00,1,5,0
+5/19/2025 0:00,1,6,0
+5/19/2025 0:00,1,7,0
+5/19/2025 0:00,1,8,0
+5/19/2025 0:00,1,9,0
+5/19/2025 0:00,1,10,0
+5/19/2025 0:00,1,11,0
+5/19/2025 0:00,1,12,0
+5/19/2025 0:00,1,13,0
+5/19/2025 0:00,1,14,0
+5/19/2025 0:00,1,15,0
+5/19/2025 0:00,1,16,0
+5/19/2025 0:00,1,17,0
+5/19/2025 0:00,1,18,0
+5/19/2025 0:00,1,19,0
+5/19/2025 0:00,1,20,0
+5/19/2025 0:00,1,21,0
+5/19/2025 0:00,1,22,0
+5/19/2025 0:00,1,23,0
+5/19/2025 0:00,1,24,0
+5/19/2025 0:00,1,25,0
+5/19/2025 0:00,1,26,0
+5/19/2025 0:00,1,27,0
+5/19/2025 0:00,1,28,0
+5/19/2025 0:00,1,29,0
+5/19/2025 0:00,1,30,0
+5/19/2025 0:00,1,31,0
+5/19/2025 0:00,1,32,0
+5/19/2025 0:00,1,33,0
+5/19/2025 0:00,1,34,0
+5/19/2025 0:00,1,35,0
+5/19/2025 0:00,1,36,0
+5/19/2025 0:00,1,37,0
+5/19/2025 0:00,1,38,0
+5/19/2025 0:00,1,39,0
+5/19/2025 0:00,1,40,0
+5/19/2025 0:00,1,41,0
+5/19/2025 0:00,1,42,0
+5/19/2025 0:00,1,43,0
+5/19/2025 0:00,1,44,0
+5/19/2025 0:00,1,45,0
+5/19/2025 0:00,1,46,0
+5/19/2025 0:00,1,47,0
+5/19/2025 0:00,1,48,0
+5/19/2025 0:00,1,49,0
+5/19/2025 0:00,1,50,0
+5/19/2025 0:00,1,51,0
+5/19/2025 0:00,1,52,0
+5/19/2025 0:00,1,53,0
+5/19/2025 0:00,1,54,0
+5/19/2025 0:00,1,55,0
+5/19/2025 0:00,1,56,0
+5/19/2025 0:00,1,57,0
+5/19/2025 0:00,1,58,0
+5/19/2025 0:00,1,59,0
+5/19/2025 0:00,1,60,0
+5/19/2025 0:00,1,61,0
+5/19/2025 0:00,1,62,0
+5/19/2025 0:00,1,63,0
+5/19/2025 0:00,1,64,0
+5/19/2025 0:00,1,65,0
+5/19/2025 0:00,1,66,0
+5/19/2025 0:00,1,67,0
+5/19/2025 0:00,1,68,0
+5/19/2025 0:00,1,69,0
+5/19/2025 0:00,1,70,0
+5/19/2025 0:00,1,71,0
\ No newline at end of file
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
new file mode 100644
index 0000000000..6bed9233ce
--- /dev/null
+++ b/imap_processing/tests/ialirt/unit/test_calculate_ingest.py
@@ -0,0 +1,107 @@
+"""Test calculate_ingest functions."""
+
+from datetime import datetime, timedelta
+
+from imap_processing import imap_module_directory
+from imap_processing.ialirt.calculate_ingest import (
+ format_ingest_data,
+ packets_created,
+)
+
+TEST_PATH = imap_module_directory / "tests" / "ialirt" / "data" / "l0"
+
+
+def test_packets_created():
+ """Test the packets_created function."""
+ with open(
+ TEST_PATH / "flight_iois_1.log.2026-021T10-58-00.171087", encoding="utf-8"
+ ) as f:
+ lines = f.readlines()
+
+ 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 == expected
+
+
+def test_format_ingest_data():
+ """Test the format_ingest_data function."""
+ base_date = datetime.strptime("2025-212", "%Y-%j")
+ filenames = []
+
+ for hour in range(24):
+ timestamp = (base_date + timedelta(hours=hour)).strftime("%Y-%jT%H_%M_%S.%f")
+ filename = f"flight_iois_1.log.{timestamp}"
+ filenames.append(filename)
+
+ log_lines = []
+ base_date = datetime.strptime("2025-212", "%Y-%j")
+
+ current_time = base_date
+ end_time = base_date + timedelta(days=1)
+
+ for _ in range(int((end_time - base_date).total_seconds())):
+ time_str = current_time.strftime("%Y/%j-%H:%M:%S.%f")[:-3]
+
+ # Kiel connection window: 08:00 to 16:00
+ if current_time == base_date + timedelta(hours=8):
+ log_lines.append(f"{time_str} Kiel antenna partner connection is up.\n")
+ elif current_time == base_date + timedelta(hours=16):
+ log_lines.append(f"{time_str} Kiel antenna partner connection is down!\n")
+
+ # Packet ingest every minute during Kiel connection window: 08:00 to 16:00
+ if (
+ base_date + timedelta(hours=8)
+ <= current_time
+ < base_date + timedelta(hours=16)
+ and current_time.minute == 0
+ and current_time.second == 0
+ ):
+ pkt_time = current_time.strftime("%Y_%j_%H_%M_%S")
+ log_lines.append(
+ f"{time_str} Renamed iois_1_packets_{pkt_time}.partial to "
+ f"iois_1_packets_{pkt_time}.\n"
+ )
+
+ 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")
+
+ 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")
+
+ current_time += timedelta(seconds=1)
+
+ filenames = sorted(filenames)
+
+ data = format_ingest_data(filenames[-1], log_lines)
+
+ 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 af31fb05d7..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):
"""
@@ -18,10 +35,7 @@ def test_generate_coverage(furnish_kernels):
"""
# Note: tested this code with the Sun and achieved expected
# results ~12 hours of coverage from horizon to horizon.
- kernels = [
- "pck00011.tpc",
- "de440s.bsp",
- ]
+ kernels = ["naif0012.tls", "pck00011.tpc", "de440s.bsp", "imap_spk_demo.bsp"]
with furnish_kernels(kernels):
coverage_dict, outage_dict = generate_coverage("2026-09-22T00:00:00Z")
@@ -42,10 +56,7 @@ def test_use_outages(furnish_kernels):
"""
# Note: tested this code with the Sun and achieved expected
# results ~12 hours of coverage from horizon to horizon.
- kernels = [
- "pck00011.tpc",
- "de440s.bsp",
- ]
+ kernels = ["naif0012.tls", "pck00011.tpc", "de440s.bsp", "imap_spk_demo.bsp"]
outages = {
"Kiel": [
@@ -58,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)
@@ -84,8 +95,10 @@ def test_dsn(furnish_kernels):
# Note: tested this code with the Sun and achieved expected
# results ~12 hours of coverage from horizon to horizon.
kernels = [
+ "naif0012.tls",
"pck00011.tpc",
"de440s.bsp",
+ "imap_spk_demo.bsp",
]
dsn = {
@@ -105,23 +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(
+ 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 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-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",
+ "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",
]
)
- np.testing.assert_array_equal(coverage_dict["Kiel"], kiel_expected)
- np.testing.assert_array_equal(coverage_dict["DSS-75"], dsn_expected)
+ time_range = np.arange(13)
- output = format_coverage_summary(coverage_dict, outage_dict, "2026-09-22T00:00:00Z")
+ 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,
+ )
- assert "I-ALiRT Coverage Summary" in output["summary"]
- assert 37.5 == output["total_coverage_percent"]
+ 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 3e381fa52a..cd4bb88826 100644
--- a/imap_processing/tests/ialirt/unit/test_ialirt_spice.py
+++ b/imap_processing/tests/ialirt/unit/test_ialirt_spice.py
@@ -11,7 +11,7 @@
get_z_axis,
transform_instrument_vectors_to_inertial,
)
-from imap_processing.spice.kernels import ensure_spice
+from imap_processing.spice.geometry import SpiceFrame, frame_transform
def test_get_z_axis():
@@ -42,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)
@@ -60,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,100 +124,55 @@ def test_compute_total_rotation():
np.testing.assert_allclose(output_vector, expected, atol=1e-9)
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
@pytest.mark.external_kernel
-@ensure_spice
-def test_transform_instrument_vectors_to_inertial(
- use_test_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,
+ mago_inertial_vector,
+ atol=1e-2,
)
- np.testing.assert_allclose(
- v_manual_1[0],
- v_spice_1,
- atol=1e-9,
- )
-
-
-@pytest.mark.use_test_metakernel("imap_ialirt_sim_metakernel.template")
-@pytest.mark.external_kernel
-@ensure_spice
-def test_no_attitude():
- """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)]),
- )
-
- # 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 76242d73c9..79cfe87e98 100644
--- a/imap_processing/tests/ialirt/unit/test_parse_mag.py
+++ b/imap_processing/tests/ialirt/unit/test_parse_mag.py
@@ -1,24 +1,40 @@
-"""Tests to support I-ALiRT MAG packet parsing."""
+"""Tests to support I-ALiRT MAG packet processing."""
+
+from unittest.mock import patch
import numpy as np
import pandas as pd
import pytest
+import spiceypy
import xarray as xr
+from scipy.interpolate import make_interp_spline
from imap_processing import imap_module_directory
from imap_processing.cdf.utils import load_cdf
from imap_processing.ialirt.l0.parse_mag import (
+ apply_gradiometry_correction,
calculate_l1b,
calibrate_and_offset_vectors,
extract_magnetic_vectors,
get_pkt_counter,
get_status_data,
get_time,
+ interpolate_spherical,
process_packet,
retrieve_matrix_from_single_l1b_calibration,
+ transform_to_frames,
+ transform_to_inertial,
)
+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.time import 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
@@ -46,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."""
@@ -92,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."""
@@ -140,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
@@ -227,16 +282,49 @@ def test_calculate_l1b(grouped_data, xarray_data, calibration_dataset):
assert "secondary_epoch" in time_data
-def test_process_packet(xarray_data, mag_test_data, calibration_dataset):
+def test_l1b_data(xarray_data, mag_test_data, calibration_dataset):
"""Tests the parse_packet function."""
- # Create fake data here since instrument packet doesn't contain it.
- xarray_data["sc_sclk_sec"] = xarray_data["mag_acq_tm_coarse"]
- xarray_data["sc_sclk_sub_sec"] = xarray_data["mag_acq_tm_fine"]
+ # Add required parameters.
+ xarray_data["met"] = calculate_time(
+ xarray_data["mag_acq_tm_coarse"], xarray_data["mag_acq_tm_fine"], 256
+ )
+ xarray_data["pkt_counter"] = get_pkt_counter(xarray_data["mag_status"])
+
+ grouped_data = find_groups(xarray_data, (0, 3), "pkt_counter", "met")
+
+ unique_groups = np.unique(grouped_data["group"])
+ l1b_data = []
+
+ for group in unique_groups:
+ # Get status values for each group.
+ status_values = grouped_data["mag_status"][
+ (grouped_data["group"] == group).values
+ ]
+ pkt_counter = grouped_data["pkt_counter"][
+ (grouped_data["group"] == group).values
+ ]
+
+ # Get decoded status data.
+ status_data = get_status_data(status_values, pkt_counter)
+
+ # Get science values for each group.
+ science_values = grouped_data["mag_data"][
+ (grouped_data["group"] == group).values
+ ]
+ science_data = extract_magnetic_vectors(science_values)
+ _, _, time_data = calculate_l1b(
+ grouped_data,
+ group,
+ pkt_counter,
+ science_data,
+ status_data,
+ calibration_dataset,
+ )
- _, parsed_packets = process_packet(xarray_data, calibration_dataset)
+ l1b_data.append({**status_data, **science_data, **time_data})
- for packet in parsed_packets:
+ for packet in l1b_data:
index = packet["pri_coarsetm"] == mag_test_data["PRI_COARSETM"]
matching_rows = mag_test_data[index]
@@ -263,10 +351,49 @@ def test_process_spacecraft_packet(
packet_path, xtce_ialirt_path, use_derived_value=False
)[478]
- mag_data, parsed_packets = process_packet(sc_xarray_data, calibration_dataset)
+ # Add required parameters.
+ sc_xarray_data["met"] = calculate_time(
+ sc_xarray_data["mag_acq_tm_coarse"], sc_xarray_data["mag_acq_tm_fine"], 256
+ )
+ sc_xarray_data["pkt_counter"] = get_pkt_counter(sc_xarray_data["mag_status"])
+
+ grouped_data = find_groups(sc_xarray_data, (0, 3), "pkt_counter", "met")
+
+ unique_groups = np.unique(grouped_data["group"])
+ l1b_data = []
+
+ for group in unique_groups:
+ # Get status values for each group.
+ status_values = grouped_data["mag_status"][
+ (grouped_data["group"] == group).values
+ ]
+ pkt_counter = grouped_data["pkt_counter"][
+ (grouped_data["group"] == group).values
+ ]
+ if not np.array_equal(pkt_counter, np.arange(4)):
+ continue
+
+ # Get decoded status data.
+ status_data = get_status_data(status_values, pkt_counter)
+
+ # Get science values for each group.
+ science_values = grouped_data["mag_data"][
+ (grouped_data["group"] == group).values
+ ]
+ science_data = extract_magnetic_vectors(science_values)
+ _, _, time_data = calculate_l1b(
+ grouped_data,
+ group,
+ pkt_counter,
+ science_data,
+ status_data,
+ calibration_dataset,
+ )
+
+ l1b_data.append({**status_data, **science_data, **time_data})
sequence = []
- for packet in parsed_packets:
+ for packet in l1b_data:
index = (mag_sc_test_data["pri_coarse"] == packet["pri_coarsetm"]) & (
mag_sc_test_data["pri_fine"] == packet["pri_fintm"]
)
@@ -305,27 +432,244 @@ def test_calibrate_and_offset_vectors(ialirt_mag_test_l1d_data):
"""Tests calibrate_and_offset_vectors function."""
# MAGo and MAGi raw counts
- mago_vectors = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
- magi_vectors = np.array([[7.0, 8.0, 9.0], [10.0, 11.0, 12.0]])
-
- # Range values (mago is 0 to 1, magi is 2 to 3)
- # Range values (0 to 3) represent MAG gain setting
- mago_range = np.array([0, 1])
- magi_range = np.array([2, 3])
+ mago_vectors = np.array([[1.0, 2.0, 3.0, 0]])
+ 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_range, mago_calibration, offsets, is_magi=False
+ mago_vectors, mago_calibration, offsets, is_magi=False
)
magi_out = calibrate_and_offset_vectors(
- magi_vectors, magi_range, magi_calibration, offsets, is_magi=True
+ magi_vectors, magi_calibration, offsets, is_magi=True
)
# Every offset is zero.
# For every range (0 to 3), the 3 by 3 calibration matrix is the identity matrix.
- np.testing.assert_allclose(mago_out, mago_vectors)
- np.testing.assert_allclose(magi_out, magi_vectors)
+ np.testing.assert_allclose(mago_out.squeeze(), mago_vectors.squeeze()[0:3])
+ np.testing.assert_allclose(magi_out.squeeze(), magi_vectors.squeeze()[0:3])
+
+
+def test_apply_gradiometry_correction(ialirt_mag_test_l1d_data):
+ """Tests apply_gradiometry_correction function."""
+
+ 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]])
+ magi_vector_eclipj2000 = np.array([[7.0, 8.0, 9.0], [10.0, 11.0, 12.0]])
+
+ time_data = {
+ "primary_epoch": np.array([1.0, 2.0]),
+ "secondary_epoch": np.array([3.0, 4.0]),
+ }
+
+ mago_corrected, magnitude = apply_gradiometry_correction(
+ mago_vector_eclipj2000,
+ np.array(time_data["primary_epoch"]),
+ magi_vector_eclipj2000,
+ np.array(time_data["secondary_epoch"]),
+ gradiometer_factor.squeeze(),
+ )
+
+ spline = make_interp_spline(
+ time_data["secondary_epoch"], magi_vector_eclipj2000, k=1
+ )
+ interpolated_vectors = spline(time_data["primary_epoch"])
+
+ # Spot check.
+ np.testing.assert_array_equal(
+ interpolated_vectors, np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
+ )
+ offset = interpolated_vectors - mago_vector_eclipj2000
+
+ offset_value = np.apply_along_axis(
+ np.dot,
+ 1,
+ offset,
+ gradiometer_factor.squeeze(),
+ )
+ expected_mago_corrected = mago_vector_eclipj2000 - offset_value
+ np.testing.assert_array_equal(mago_corrected, expected_mago_corrected)
+
+ expected_magnitude = np.sqrt(np.sum(mago_corrected**2, axis=1))
+ np.testing.assert_array_equal(magnitude, expected_magnitude)
+
+
+@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_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])
+ dec = np.array([90.0, 90.0, 90.0, 90.0])
+ spin_phase = np.array([0.0, 90.0, 180.0, 270.0]) # degrees
+
+ # Unit vector pointing along +X in instrument frame
+ mag_vector = np.array([1.0, 0.0, 0.0])
+
+ attitude_time = np.array([817561851.0, 817561853.0, 817561855.0, 817561857.0])
+ 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),
+ np.radians(dec),
+ et_to_ttj2000ns(attitude_time),
+ et_to_ttj2000ns(target_time),
+ mag_vector,
+ inst_frame,
+ )
+
+ gse_vector, gsm_vector, rtn_vector = transform_to_frames(
+ et_to_ttj2000ns(target_time),
+ inertial_vector,
+ )
+
+ rot_ecl_to_gse = spiceypy.pxform(
+ SpiceFrame.ECLIPJ2000.name, SpiceFrame.IMAP_GSE.name, target_time
+ )
+ expected_gse = spiceypy.mxv(rot_ecl_to_gse, inertial_vector)
+ rot_ecl_to_gsm = spiceypy.pxform(
+ SpiceFrame.ECLIPJ2000.name, SpiceFrame.IMAP_GSM.name, target_time
+ )
+ expected_gsm = spiceypy.mxv(rot_ecl_to_gsm, inertial_vector)
+ rot_ecl_to_rtn = spiceypy.pxform(
+ SpiceFrame.ECLIPJ2000.name, SpiceFrame.IMAP_RTN.name, target_time
+ )
+ expected_rtn = spiceypy.mxv(rot_ecl_to_rtn, inertial_vector)
+
+ 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(
+ postlaunch_xarray_data,
+ calibration_dataset,
+ ialirt_mag_test_l1d_data_postlaunch,
+ furnish_kernels,
+):
+ """Test the process_packet 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):
+ mag_data = process_packet(
+ postlaunch_xarray_data,
+ calibration_dataset,
+ ialirt_mag_test_l1d_data_postlaunch,
+ )
+
+ assert isinstance(mag_data[0], dict)
+ expected_keys = {
+ "apid",
+ "met",
+ "met_in_utc",
+ "ttj2000ns",
+ "mag_epoch",
+ "mag_B_GSE",
+ "mag_B_GSM",
+ "mag_B_RTN",
+ "mag_B_magnitude",
+ "mag_phi_B_GSM",
+ "mag_theta_B_GSM",
+ "mag_phi_B_GSE",
+ "mag_theta_B_GSE",
+ }
+ assert expected_keys.issubset(mag_data[0].keys())
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 849053b394..6875a4fbd2 100644
--- a/imap_processing/tests/ialirt/unit/test_process_ephemeris.py
+++ b/imap_processing/tests/ialirt/unit/test_process_ephemeris.py
@@ -16,26 +16,27 @@ def test_calculate_doppler(furnish_kernels):
latitude = -33.94 # latitude in degrees
altitude = 0.157 # altitude in kilometers
# test single observation time
- observation_time = 843307269.1823885 # "2026-09-22T00:00:00.000"
+ observation_time = 811771269.1823868 # "2025-09-22T00:00:00.000"
kernels = [
+ "naif0012.tls",
"pck00011.tpc",
"imap_spk_demo.bsp",
"de440s.bsp",
- "earth_1962_240827_2124_combined.bpc",
+ "earth_latest_high_prec.bpc",
]
with furnish_kernels(kernels):
doppler_result = process_ephemeris.calculate_doppler(
longitude, latitude, altitude, observation_time
)
- assert doppler_result is not None
+ assert doppler_result is not None
- # test array of observation times
- time_endpoints = ("2026 SEP 22 00:00:00", "2026 SEP 22 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
- )
+ # test array of observation times
+ time_endpoints = ("2025 SEP 22 00:00:00", "2025 SEP 22 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
+ )
with furnish_kernels(kernels):
doppler_result = process_ephemeris.calculate_doppler(
longitude, latitude, altitude, observation_time
@@ -75,27 +76,30 @@ def test_calculate_azimuth_and_elevation(furnish_kernels):
observation_time = 805794429.1837295 # "2025-07-14T19:46:00.000"
kernels = [
+ "naif0012.tls",
"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
+ 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_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
- )
+ # test array of observation times
+ 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
+ )
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)
@@ -111,7 +115,7 @@ def test_build_output(furnish_kernels):
longitude = -71.41 # longitude in degrees
latitude = -33.94 # latitude in degrees
altitude = 0.157 # altitude in kilometers
- time_endpoints = ("2026 SEP 22 00:00:00", "2026 SEP 22 23:59:59")
+ time_endpoints = ("2025 SEP 22 00:00:00", "2025 SEP 22 23:59:59")
time_interval = int(1e3) # seconds between data points
kernels = [
@@ -119,19 +123,35 @@ def test_build_output(furnish_kernels):
"pck00011.tpc",
"de440s.bsp",
"imap_spk_demo.bsp",
- "earth_1962_240827_2124_combined.bpc",
+ "earth_latest_high_prec.bpc",
]
with furnish_kernels(kernels):
output_dict = process_ephemeris.build_output(
longitude, latitude, altitude, time_endpoints, time_interval
)
- for key_name in ["azimuth", "elevation", "time", "doppler"]:
- assert key_name in output_dict.keys()
- assert len(output_dict[key_name]) == len(
- np.arange(
- str_to_et(time_endpoints[0]),
- str_to_et(time_endpoints[1]),
- time_interval,
+ for key_name in ["azimuth", "elevation", "time", "doppler"]:
+ assert key_name in output_dict.keys()
+ assert len(output_dict[key_name]) == len(
+ np.arange(
+ str_to_et(time_endpoints[0]),
+ str_to_et(time_endpoints[1]),
+ time_interval,
+ )
)
- )
+
+
+@pytest.mark.external_kernel
+def test_generate_text_files(furnish_kernels, tmpdir):
+ kernels = [
+ "naif0012.tls",
+ "pck00011.tpc",
+ "de440s.bsp",
+ "imap_spk_demo.bsp",
+ "earth_latest_high_prec.bpc",
+ ]
+ with furnish_kernels(kernels):
+ output = process_ephemeris.generate_text_files(station="Kiel", day="2025-08-15")
+
+ assert output[0] == "Station: Kiel\n"
+ assert "(km/s)\n" in output[7]
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 c3da32ed28..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."""
@@ -74,7 +96,7 @@ def ialirt_test_data():
"""Extract test data for unit tests below."""
energy_data = pd.read_csv(
- f"{imap_module_directory}/tests/ialirt/test_data/ialirt_test_data.csv"
+ f"{imap_module_directory}/tests/ialirt/data/l0/ialirt_test_data.csv"
)
count_rates = energy_data["Count Rates [Hz]"].to_numpy()
count_rates = np.tile(count_rates, (2, 1))
@@ -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,30 +163,19 @@ def test_process_swapi_ialirt(
0 : xarray_data["swapi_flag"].shape[0]
].data
- swapi_result = process_swapi_ialirt(xarray_data)
-
- key_names = [
- "apid",
- "met",
- "met_in_utc",
- "ttj2000ns",
- "swapi_pseudo_proton_density",
- "swapi_pseudo_proton_speed",
- "swapi_pseudo_proton_temperature",
- ]
+ swapi_result = process_swapi_ialirt(xarray_data, esa_unit_conversion_table)
- 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 = 621.0028766348703
- 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 "
@@ -168,58 +183,300 @@ def test_count_rate():
)
-@pytest.mark.skip(reason="Differences between scipy versions.")
-def test_optimize_parameters(xarray_data, ialirt_test_data):
+def test_optimize_parameters():
"""Test that the optimize_pseudo_parameters() function works correctly."""
- result = optimize_pseudo_parameters(*ialirt_test_data)
+ # The following files and values are all validation sets provided by the SWAPI team.
+ test_data = {
+ "test_set_1": {
+ "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 / 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 / Consts.temporary_density_factor, 0.3),
+ "pseudo_temperature": (1.2e5, 0.28),
+ },
+ },
+ "test_set_3": {
+ "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 / Consts.temporary_density_factor, 0.39),
+ "pseudo_temperature": (8e4, 0.2),
+ },
+ },
+ }
+
+ 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)
+
+ for test_set in test_data:
+ energy_data = pd.read_csv(
+ f"{imap_module_directory}/tests/ialirt/data/l0/"
+ f"{test_data[test_set]['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()
+
+ 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_dict[param],
+ test_data[test_set]["expected_values"][param][0],
+ rtol=test_data[test_set]["expected_values"][param][1],
+ ),
+ f"{param} did not match the expected result within the tolerance.",
+ )
+
+
+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,
+ )
+
+ 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]
- # Test output corresponding to this exact set of test inputs.
- expected_speed = [550.2067500045512, 550.2067500045512]
- expected_density = [15.964441588773008, 15.964441588773008]
- expected_temperature = [101695.2160638631, 101695.2160638631]
+ 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]
- assert np.allclose(result["pseudo_speed"], expected_speed, rtol=0.01), (
- "Pseudo speed did not match the expected result."
+ 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,
)
- assert np.allclose(result["pseudo_density"], expected_density, rtol=0.01), (
- "Pseudo density did not match the expected result."
+
+ 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 np.allclose(result["pseudo_temperature"], expected_temperature, rtol=0.01), (
- "Pseudo temperature did not match the expected result."
+ 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,
+ ]
+
+ 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(sc_xarray_data):
+def test_process_spacecraft_packet(
+ esa_unit_conversion_table, swapi_postlaunch_sc_packet_path
+):
"""Tests spacecraft packet processing."""
- # Case 1: Not fixing the sequence number attribute, which is all zeros.
- swapi_product = process_swapi_ialirt(sc_xarray_data)
- 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)
- key_names = [
- "apid",
- "met",
- "met_in_utc",
- "ttj2000ns",
- "swapi_pseudo_proton_density",
- "swapi_pseudo_proton_speed",
- "swapi_pseudo_proton_temperature",
- ]
+ 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")
- 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."
- )
+ 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 74a3b95c92..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():
@@ -220,7 +221,7 @@ def test_phi_to_bin():
expected_bins = np.arange(30)
- for phi, expected_bin in zip(phis, expected_bins):
+ for phi, expected_bin in zip(phis, expected_bins, strict=False):
assert phi_to_bin(phi) == expected_bin
@@ -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 afc0061973..add6dd9ad9 100644
--- a/imap_processing/tests/idex/conftest.py
+++ b/imap_processing/tests/idex/conftest.py
@@ -6,22 +6,21 @@
from imap_processing import imap_module_directory
from imap_processing.cdf.utils import load_cdf
-from imap_processing.idex.idex_constants import NANOSECONDS_IN_DAY, SPICE_ARRAYS
+from imap_processing.idex.idex_constants import SPICE_ARRAYS
from imap_processing.idex.idex_l1a import PacketParser
from imap_processing.idex.idex_l1b import idex_l1b
-from imap_processing.idex.idex_l2b import idex_l2b
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
@@ -51,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_EVT).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 idex_l1b(decom_test_data_msg, "msg")
@pytest.fixture
@@ -113,29 +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)
- return dataset
-
-
-@pytest.fixture
-def l2b_dataset(l2a_dataset: xr.Dataset) -> xr.Dataset:
- """Return a ``xarray`` dataset containing test data.
-
- Returns
- -------
- dataset : xr.Dataset
- A ``xarray`` dataset containing the test data
- """
- l1b_evt_dataset = load_cdf(L1B_EVT_CDF)
- l1b_evt_dataset2 = (
- l1b_evt_dataset.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
- l2a_dataset2["epoch"] = l2a_dataset2["epoch"] + NANOSECONDS_IN_DAY
- dataset = idex_l2b([l2a_dataset, l2a_dataset2], [l1b_evt_dataset, l1b_evt_dataset2])
+ dataset = idex_l1b(decom_test_data_sci, "sci-1week")
return dataset
@@ -215,3 +204,15 @@ def load_hdf_file(path: str) -> xr.Dataset:
example_dataset = xr.concat(datasets, dim="event")
return example_dataset
+
+
+@pytest.fixture
+def ancillary_files():
+ """Fixture to return ancillary files."""
+ path = imap_module_directory / "tests" / "idex" / "test_data"
+ return {
+ "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_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 4d96c9538f..09a7abc2a0 100644
--- a/imap_processing/tests/idex/test_idex_l2a.py
+++ b/imap_processing/tests/idex/test_idex_l2a.py
@@ -3,6 +3,7 @@
from unittest import mock
import numpy as np
+import pandas as pd
import pytest
import xarray as xr
from scipy.stats import exponnorm
@@ -16,10 +17,14 @@
butter_lowpass_filter,
calculate_kappa,
calculate_snr,
+ calculate_velocity_and_mass,
chi_square,
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,
@@ -28,7 +33,9 @@
@pytest.fixture
-def l2a_dataset(l1b_dataset: xr.Dataset, decom_test_data_sci) -> xr.Dataset:
+def l2a_dataset(
+ l1b_dataset: xr.Dataset, decom_test_data_sci, ancillary_files, _download_test_data
+) -> xr.Dataset:
"""Return a ``xarray`` dataset containing test data.
Returns
-------
@@ -45,7 +52,7 @@ def l2a_dataset(l1b_dataset: xr.Dataset, decom_test_data_sci) -> xr.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))
+ dataset = idex_l2a(idex_l1b(decom_test_data_sci, "sci-1week"), ancillary_files)
return dataset
@@ -62,6 +69,14 @@ 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
with the expected logical source.
@@ -86,18 +101,21 @@ def test_l2a_logical_source_and_cdf(l2a_dataset: xr.Dataset):
"target_low_fit_parameters",
"target_low_impact_charge",
"target_low_dust_mass_estimate",
+ "target_low_velocity_estimate",
"target_low_chi_squared",
"target_low_reduced_chi_squared",
"target_low_fit_results",
"target_high_fit_parameters",
"target_high_impact_charge",
"target_high_dust_mass_estimate",
+ "target_high_velocity_estimate",
"target_high_chi_squared",
"target_high_reduced_chi_squared",
"target_high_fit_results",
"ion_grid_fit_parameters",
"ion_grid_impact_charge",
"ion_grid_dust_mass_estimate",
+ "ion_grid_velocity_estimate",
"ion_grid_chi_squared",
"ion_grid_reduced_chi_squared",
"ion_grid_fit_results",
@@ -118,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():
"""
@@ -267,6 +303,123 @@ 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-t-rise"], skiprows=1, header=None
+ ).values.flatten()[:8]
+ yield_params = pd.read_csv(
+ ancillary_files["l2a-calibration-curve-yield-params"], skiprows=1, header=None
+ ).values.flatten()[:8]
+ 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():
"""Tests that analyze_peaks() returns the expected fit params and areas."""
event = 0
@@ -343,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 1b25a9ceef..cf3c5bc44c 100644
--- a/imap_processing/tests/idex/test_idex_l2b.py
+++ b/imap_processing/tests/idex/test_idex_l2b.py
@@ -1,12 +1,14 @@
"""Tests the L2b processing for IDEX data"""
import numpy as np
+import pytest
import xarray as xr
from numpy.testing import assert_array_equal
from imap_processing.cdf.utils import write_cdf
from imap_processing.idex.idex_constants import (
FG_TO_KG,
+ IDEX_SPACING_DEG,
NANOSECONDS_IN_DAY,
SECONDS_IN_DAY,
)
@@ -19,19 +21,43 @@
compute_counts_by_charge_and_mass,
compute_rates_by_charge_and_mass,
get_science_acquisition_on_percentage,
- get_science_acquisition_timestamps,
+ idex_l2b,
)
-def test_l2b_logical_source_and_cdf(l2b_dataset: xr.Dataset):
+@pytest.fixture
+def l2b_and_l2c_datasets(l2a_dataset: xr.Dataset, test_l1b_msg) -> list[xr.Dataset]:
+ """Return a ``xarray`` dataset containing test data.
+
+ Returns
+ -------
+ datasets : list[xr.Dataset]
+ A list of ``xarray`` datasets containing the test data for L2B and L2C.
+ """
+ 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_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], [test_l1b_msg.copy(), l1b_msg_dataset2]
+ )
+ return datasets
+
+
+def test_l2b_logical_source_and_cdf(l2b_and_l2c_datasets: list[xr.Dataset]):
"""Tests that the ``idex_l2b`` function generates datasets
with the expected logical source.
Parameters
----------
- l2b_dataset : xr.Dataset
+ l2b_and_l2c_datasets : list[xr.Dataset]
A ``xarray`` dataset containing the test data
"""
+ l2b_dataset = l2b_and_l2c_datasets[0]
expected_src = "imap_idex_l2b_sci-1mo"
assert l2b_dataset.attrs["Logical_source"] == expected_src
# Verify the CDF file can be created with no errors.
@@ -42,13 +68,69 @@ def test_l2b_logical_source_and_cdf(l2b_dataset: xr.Dataset):
assert file_name.name == "imap_idex_l2b_sci-1mo_20251017_v999.cdf"
-def test_l2b_cdf_variables(l2b_dataset: xr.Dataset):
+def test_l2c_attrs_and_vars(
+ l2b_and_l2c_datasets: list[xr.Dataset], l2a_dataset: xr.Dataset
+):
+ """Tests that the ``idex_l2b`` function generates datasets
+ with the expected variables and attributes.
+
+ Parameters
+ ----------
+ l2b_and_l2c_datasets : list[xr.Dataset]
+ A ``xarray`` dataset containing the l2c test data.
+ l2a_dataset
+ A ``xarray`` dataset containing the l1b test data.
+ """
+ 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
+ # )
+ assert l2c_dataset.sizes == {
+ "on_off_times": 4,
+ "epoch": 2,
+ "impact_charge": 10,
+ "mass": 10,
+ "rectangular_lon_pixel": int(360 / IDEX_SPACING_DEG),
+ "rectangular_lat_pixel": int(180 / IDEX_SPACING_DEG),
+ }
+ l2c_dataset.attrs["Data_version"] = "999"
+ # Check the attributes of the dataset by writing to a CDF file
+ rect_file_name = write_cdf(l2c_dataset)
+ assert rect_file_name.exists()
+ assert rect_file_name.name == "imap_idex_l2c_rectangular-map-1mo_20251017_v999.cdf"
+
+ for var in l2c_dataset.data_vars:
+ assert "DICT_KEY" in l2c_dataset[var].attrs, (
+ 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
with the expected variables.
Parameters
----------
- l2b_dataset : xr.Dataset
+ l2b_and_l2c_datasets : list[xr.Dataset]
A ``xarray`` dataset containing the test data
"""
expected_vars = [
@@ -58,12 +140,8 @@ def test_l2b_cdf_variables(l2b_dataset: xr.Dataset):
"counts_by_mass",
"rate_by_charge",
"rate_by_mass",
- "counts_by_charge_map",
- "counts_by_mass_map",
- "rate_by_charge_map",
- "rate_by_mass_map",
]
-
+ l2b_dataset = l2b_and_l2c_datasets[0]
cdf_vars = l2b_dataset.variables
for var in expected_vars:
assert var in cdf_vars
@@ -72,6 +150,18 @@ def test_l2b_cdf_variables(l2b_dataset: 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."""
@@ -107,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
@@ -150,6 +223,13 @@ def test_get_science_acquisition_on_percentage(decom_test_data_evt: list[xr.Data
assert on_percentages[9] < 1 # The uptime should be less than 1%
+def test_get_science_acquisition_on_percentage_no_acquisition(caplog):
+ """Test the function returns an empty dict when there is no science acquisition."""
+ on_percentages = get_science_acquisition_on_percentage(np.array([]), np.array([]))
+ assert not on_percentages
+ assert "No science acquisition events found" in caplog.text
+
+
def test_compute_counts_by_charge_and_mass():
"""Test the compute_counts_by_charge_and_mass function."""
@@ -161,6 +241,7 @@ def test_compute_counts_by_charge_and_mass():
# and mass bins all in the first spin phase bin. The test should be zero. This
# should be the same for each epoch except the second epoch which has 2 counts in
# the first 5 mass and impact charge bins.
+
l2a_dataset = xr.Dataset(
{
"epoch": epochs,
@@ -398,3 +479,45 @@ def test_compute_rates_by_charge_and_mass_missing_acquisition_time(caplog):
# Assert that quality flags are 0 for the missing acquisition time
assert quality_flags[0] == 1
assert quality_flags[1] == 0
+
+
+def test_compute_rates_no_acquisition_data(caplog):
+ """Test that the function produces -1 rates when hk data isn't available."""
+ caplog.at_level("WARNING")
+ # Mock example inputs
+ counts_by_charge = np.ones(
+ (2, len(CHARGE_BIN_EDGES), len(SPIN_PHASE_BIN_EDGES) - 1)
+ )
+ counts_by_mass = counts_by_charge
+ counts_by_charge_map = np.ones(
+ (
+ 2,
+ len(CHARGE_BIN_EDGES),
+ len(SKY_GRID.az_bin_edges) - 1,
+ len(SKY_GRID.el_bin_edges) - 1,
+ )
+ )
+ counts_by_mass_map = counts_by_charge_map
+ # Mock DOY values for the epochs
+ epoch_doy = np.array([1, 2])
+ # Mock daily idex uptime percentages. Purposefully leave out day 2 to simulate
+ # missing acquisition times
+ daily_on_percentage = {}
+ # Compute the rates by charge and mass and assert there is a warning in the logs.
+ rate_by_charge, rate_by_mass, rate_mass_map, rate_charge_map, quality_flags = (
+ compute_rates_by_charge_and_mass(
+ counts_by_charge,
+ counts_by_mass,
+ counts_by_charge_map,
+ counts_by_mass_map,
+ epoch_doy,
+ daily_on_percentage,
+ )
+ )
+
+ # All rates by charge and mass should be -1.0
+ np.testing.assert_array_equal(rate_by_charge, np.full(rate_by_charge.shape, -1.0))
+ np.testing.assert_array_equal(rate_by_mass, np.full(rate_by_mass.shape, -1.0))
+
+ # Assert that quality flags are all 0 for missing acquisition times
+ np.testing.assert_array_equal(quality_flags, np.full(quality_flags.shape, 0))
diff --git a/imap_processing/tests/idex/test_idex_l2c.py b/imap_processing/tests/idex/test_idex_l2c.py
deleted file mode 100644
index 76a1a06c8e..0000000000
--- a/imap_processing/tests/idex/test_idex_l2c.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""Tests the L2c processing for IDEX data"""
-
-import numpy as np
-import pytest
-import xarray as xr
-
-from imap_processing.cdf.utils import write_cdf
-from imap_processing.idex.idex_constants import (
- IDEX_SPACING_DEG,
-)
-from imap_processing.idex.idex_l2c import idex_l2c
-
-
-@pytest.fixture
-def l2c_dataset(l2b_dataset: xr.Dataset) -> xr.Dataset:
- """Return a ``xarray`` dataset containing test data.
-
- Returns
- -------
- dataset : list[xr.Dataset]
- A list of ``xarray`` datasets containing the test data
- """
-
- return idex_l2c([l2b_dataset])
-
-
-def test_l2c_attrs_and_vars(l2c_dataset: xr.Dataset, l2a_dataset: xr.Dataset):
- """Tests that the ``idex_l2b`` function generates datasets
- with the expected variables and attributes.
-
- Parameters
- ----------
- l2c_dataset : xr.Dataset
- A ``xarray`` dataset containing the l2c test data.
- l2a_dataset
- A ``xarray`` dataset containing the l1b test data.
- """
- assert l2c_dataset.attrs["Logical_source"] == "imap_idex_l2c_rectangular-map-1mo"
- # 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
- )
- assert l2c_dataset.sizes == {
- "epoch": 2,
- "impact_charge": 10,
- "mass": 10,
- "rectangular_lon_pixel": int(360 / IDEX_SPACING_DEG),
- "rectangular_lat_pixel": int(180 / IDEX_SPACING_DEG),
- }
- l2c_dataset.attrs["Data_version"] = "999"
- # Check the attributes of the dataset by writing to a CDF file
- rect_file_name = write_cdf(l2c_dataset)
- assert rect_file_name.exists()
- assert rect_file_name.name == "imap_idex_l2c_rectangular-map-1mo_20251017_v999.cdf"
-
- for var in l2c_dataset.data_vars:
- assert "DICT_KEY" in l2c_dataset[var].attrs, (
- f"Variable {var} is missing the DICT_KEY attribute for SPASE metadata."
- )
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_efficiency-factor-small_20250101_20270101_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_efficiency-factor-small_20250101_20270101_v001.csv
new file mode 100644
index 0000000000..7b833318f1
--- /dev/null
+++ b/imap_processing/tests/lo/test_anc/imap_lo_efficiency-factor-small_20250101_20270101_v001.csv
@@ -0,0 +1,32 @@
+ο»Ώ#YYYYDDD,E-Step1_eff,E-Step2_eff,E-Step3_eff,E-Step4_eff,E-Step5_eff,E-Step6_eff,E-Step7_eff,#Comments
+2025001,1,1,1,1,1,1,1,Hi Track HiThr
+2025002,1,1,1,1,1,1,1,Hi Track HiRes
+2025003,1,1,1,1,1,1,1,Hi Track HiThr
+2025004,1,1,1,1,1,1,1,Hi Track HiRes
+2025005,1,1,1,1,1,1,1,Hi Track HiThr
+2025006,1,1,1,1,1,1,1,Hi Track HiRes
+2025007,1,1,1,1,1,1,1,Hi Track HiThr
+2025008,1,1,1,1,1,1,1,Hi Track HiRes
+2025009,1,1,1,1,1,1,1,Hi Track HiThr
+2025010,1,1,1,1,1,1,1,Hi Track HiRes
+2025011,1,1,1,1,1,1,1,Hi Track HiThr
+2025012,1,1,1,1,1,1,1,Hi Track HiRes
+2025013,1,1,1,1,1,1,1,Hi Track HiThr
+2025014,1,1,1,1,1,1,1,Hi Track HiRes
+2025015,1,1,1,1,1,1,1,Hi Track HiThr
+2025016,1,1,1,1,1,1,1,Hi Track HiThr
+2025017,1,1,1,1,1,1,1,Hi Track HiRes
+2025018,1,1,1,1,1,1,1,Hi Track HiThr
+2025019,1,1,1,1,1,1,1,Hi Track HiRes
+2025020,1,1,1,1,1,1,1,Hi Track HiThr
+2025021,1,1,1,1,1,1,1,Hi Track HiRes
+2025022,0.93,0.93,0.93,0.93,0.93,0.92,0.92,Lo Track HiThr
+2025023,1,1,1,1,1,1,1,Hi Track HiRes
+2025024,1,1,1,1,1,1,1,Hi Track HiThr
+2025025,1,1,1,1,1,1,1,Hi Track HiRes
+2025026,1,1,1,1,1,1,1,Hi Track HiThr
+2025027,1,1,1,1,1,1,1,Hi Track HiRes
+2025028,1,1,1,1,1,1,1,Hi Track HiThr
+2025029,1,1,1,1,1,1,1,Hi Track HiRes
+2025030,1,1,1,1,1,1,1,Hi Track HiThr
+2025031,1,1,1,1,1,1,1,Hi Track HiThr
\ No newline at end of file
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
new file mode 100644
index 0000000000..0564987f13
--- /dev/null
+++ b/imap_processing/tests/lo/test_anc/imap_lo_esa-mode-lut_v001.csv
@@ -0,0 +1,114 @@
+ο»Ώ-1 is used for ESA Level for the background mode as the voltages are not associated with any of the nominal E-Steps.,,,,,,,
+Tbl_Idx,E-Step_Idx,E-Step_lvl,ESA_POS_V,ESA_NEG_V,ESA_POS_Raw,ESA_NEG_Raw,ESA_Mode
+0,1,1,61.9,30.5,66,67,HiThr
+0,2,2,119.4,58.9,133,135,HiThr
+0,3,3,229.4,113.2,262,266,HiThr
+0,4,4,451.5,222.8,523,530,HiThr
+0,5,5,870.6,429.5,1016,1028,HiThr
+0,6,6,1782.4,879.4,2087,2111,HiThr
+0,7,7,3453.8,1704.1,4050,4095,HiThr
+1,1,1,40.3,13.7,40,26,HiRes
+1,2,2,77.7,26.3,84,57,HiRes
+1,3,3,149.3,50.6,168,115,HiRes
+1,4,4,293.9,99.6,338,233,HiRes
+1,5,5,566.7,192,659,456,HiRes
+1,6,6,1160.2,393,1356,940,HiRes
+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,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
+3,4,2,77.7,26.3,84,57,HiRes
+3,5,2,77.7,26.3,84,57,HiRes
+3,6,2,77.7,26.3,84,57,HiRes
+3,7,2,77.7,26.3,84,57,HiRes
+4,1,3,149.3,50.6,168,115,HiRes
+4,2,3,149.3,50.6,168,115,HiRes
+4,3,3,149.3,50.6,168,115,HiRes
+4,4,3,149.3,50.6,168,115,HiRes
+4,5,3,149.3,50.6,168,115,HiRes
+4,6,3,149.3,50.6,168,115,HiRes
+4,7,3,149.3,50.6,168,115,HiRes
+5,1,4,293.9,99.6,338,233,HiRes
+5,2,4,293.9,99.6,338,233,HiRes
+5,3,4,293.9,99.6,338,233,HiRes
+5,4,4,293.9,99.6,338,233,HiRes
+5,5,4,293.9,99.6,338,233,HiRes
+5,6,4,293.9,99.6,338,233,HiRes
+5,7,4,293.9,99.6,338,233,HiRes
+6,1,5,566.7,192,659,456,HiRes
+6,2,5,566.7,192,659,456,HiRes
+6,3,5,566.7,192,659,456,HiRes
+6,4,5,566.7,192,659,456,HiRes
+6,5,5,566.7,192,659,456,HiRes
+6,6,5,566.7,192,659,456,HiRes
+6,7,5,566.7,192,659,456,HiRes
+7,1,6,1160.2,393,1356,940,HiRes
+7,2,6,1160.2,393,1356,940,HiRes
+7,3,6,1160.2,393,1356,940,HiRes
+7,4,6,1160.2,393,1356,940,HiRes
+7,5,6,1160.2,393,1356,940,HiRes
+7,6,6,1160.2,393,1356,940,HiRes
+7,7,6,1160.2,393,1356,940,HiRes
+8,1,7,2248.3,761.6,2634,1827,HiRes
+8,2,7,2248.3,761.6,2634,1827,HiRes
+8,3,7,2248.3,761.6,2634,1827,HiRes
+8,4,7,2248.3,761.6,2634,1827,HiRes
+8,5,7,2248.3,761.6,2634,1827,HiRes
+8,6,7,2248.3,761.6,2634,1827,HiRes
+8,7,7,2248.3,761.6,2634,1827,HiRes
+9,1,-1,61.9,1704.1,66,4095,BKG
+9,2,-1,61.9,1704.1,66,4095,BKG
+9,3,-1,61.9,1704.1,66,4095,BKG
+9,4,-1,61.9,1704.1,66,4095,BKG
+9,5,-1,61.9,1704.1,66,4095,BKG
+9,6,-1,61.9,1704.1,66,4095,BKG
+9,7,-1,61.9,1704.1,66,4095,BKG
+10,1,2,119.4,58.9,133,135,HiThr
+10,2,2,119.4,58.9,133,135,HiThr
+10,3,2,119.4,58.9,133,135,HiThr
+10,4,2,119.4,58.9,133,135,HiThr
+10,5,2,119.4,58.9,133,135,HiThr
+10,6,2,119.4,58.9,133,135,HiThr
+10,7,2,119.4,58.9,133,135,HiThr
+11,1,3,229.4,113.2,262,266,HiThr
+11,2,3,229.4,113.2,262,266,HiThr
+11,3,3,229.4,113.2,262,266,HiThr
+11,4,3,229.4,113.2,262,266,HiThr
+11,5,3,229.4,113.2,262,266,HiThr
+11,6,3,229.4,113.2,262,266,HiThr
+11,7,3,229.4,113.2,262,266,HiThr
+12,1,4,451.5,222.8,523,530,HiThr
+12,2,4,451.5,222.8,523,530,HiThr
+12,3,4,451.5,222.8,523,530,HiThr
+12,4,4,451.5,222.8,523,530,HiThr
+12,5,4,451.5,222.8,523,530,HiThr
+12,6,4,451.5,222.8,523,530,HiThr
+12,7,4,451.5,222.8,523,530,HiThr
+13,1,5,870.6,429.5,1016,1028,HiThr
+13,2,5,870.6,429.5,1016,1028,HiThr
+13,3,5,870.6,429.5,1016,1028,HiThr
+13,4,5,870.6,429.5,1016,1028,HiThr
+13,5,5,870.6,429.5,1016,1028,HiThr
+13,6,5,870.6,429.5,1016,1028,HiThr
+13,7,5,870.6,429.5,1016,1028,HiThr
+14,1,6,1782.4,879.4,2087,2111,HiThr
+14,2,6,1782.4,879.4,2087,2111,HiThr
+14,3,6,1782.4,879.4,2087,2111,HiThr
+14,4,6,1782.4,879.4,2087,2111,HiThr
+14,5,6,1782.4,879.4,2087,2111,HiThr
+14,6,6,1782.4,879.4,2087,2111,HiThr
+14,7,6,1782.4,879.4,2087,2111,HiThr
+15,1,7,3453.8,1704.1,4050,4095,HiThr
+15,2,7,3453.8,1704.1,4050,4095,HiThr
+15,3,7,3453.8,1704.1,4050,4095,HiThr
+15,4,7,3453.8,1704.1,4050,4095,HiThr
+15,5,7,3453.8,1704.1,4050,4095,HiThr
+15,6,7,3453.8,1704.1,4050,4095,HiThr
+15,7,7,3453.8,1704.1,4050,4095,HiThr
\ No newline at end of file
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
new file mode 100644
index 0000000000..fbc88964ec
--- /dev/null
+++ b/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-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_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_pointing-Index_20250101_20271231_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_pointing-Index_20250101_20271231_v001.csv
new file mode 100644
index 0000000000..7d91ad23a1
--- /dev/null
+++ b/imap_processing/tests/lo/test_anc/imap_lo_pointing-Index_20250101_20271231_v001.csv
@@ -0,0 +1,16 @@
+ο»ΏIndex,Nominal_Angle(deg),Min_Angle(deg),Max_Angle(deg),YYYYDDD_strt,YYYYDDD_end
+1,60,55,65,2027207,2027363
+2,75,70,80,2025003,2025363
+2,75,70,80,2026003,2026363
+2,75,70,80,2027001,2027033
+2,75,70,80,2027281,2027365
+3,90,85,95,2025002,2025364
+3,90,85,95,2026002,2026364
+3,90,85,95,2027002,2027362
+4,105,100,110,2025001,2025365
+4,105,100,110,2026001,2026365
+4,105,100,110,2027003,2027151
+5,120,115,125,2027037,2027189
+6,135,130,140,2027004,2027364
+7,148,143,153,2027155,2027203
+8,160,155,165,2027193,2027277
\ No newline at end of file
diff --git a/imap_processing/tests/lo/test_anc/imap_lo_pointing-file-small_20250101_20271231_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_pointing-file-small_20250101_20271231_v001.csv
new file mode 100644
index 0000000000..08513ce103
--- /dev/null
+++ b/imap_processing/tests/lo/test_anc/imap_lo_pointing-file-small_20250101_20271231_v001.csv
@@ -0,0 +1,6 @@
+ο»ΏYYYYDDD,Map_Index,Nominal_Angle (deg)
+2025001,4,105
+2025002,3,90
+2025003,2,75
+2025004,3,90
+2025005,4,105
\ No newline at end of file
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
new file mode 100644
index 0000000000..6b4d507a81
--- /dev/null
+++ b/imap_processing/tests/lo/test_anc/imap_lo_sweep-table-small_20250101_20260301_v001.csv
@@ -0,0 +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,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
new file mode 100644
index 0000000000..f167e63d85
--- /dev/null
+++ b/imap_processing/tests/lo/test_lo_ancillary.py
@@ -0,0 +1,201 @@
+import numpy as np
+import pandas as pd
+
+from imap_processing import imap_module_directory
+from imap_processing.lo import lo_ancillary
+
+ANCILLARY_DIR = imap_module_directory / "tests/lo/test_anc"
+
+
+def test_read_backgrounds():
+ ancillary_file = (
+ ANCILLARY_DIR / "imap_lo_hydrogen-background-small_20250101_20270101_v001.csv"
+ )
+ df = lo_ancillary.read_ancillary_file(ancillary_file)
+ assert len(df) == 240
+
+ # spot check the first row
+ first_row = df.iloc[0]
+ np.testing.assert_array_equal(
+ first_row,
+ np.array(
+ [
+ pd.Timestamp("2025-01-01"),
+ 473389200.0,
+ 473472000.0,
+ 0,
+ 0,
+ "Lo",
+ 0.0098,
+ 0.0089,
+ 0.0118,
+ 0.0113,
+ 0.0056,
+ 0.0008,
+ 0.0000,
+ "rate",
+ ],
+ dtype=object,
+ ),
+ )
+
+
+def test_read_geometric_factor():
+ # 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
+ assert all(df.loc[:35, "esa_mode"] == 0)
+ assert all(df.loc[36:, "esa_mode"] == 1)
+
+ # spot check the first row
+ np.testing.assert_array_equal(
+ df.iloc[0],
+ [
+ 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,
+ 0,
+ ],
+ )
+
+ # Make sure we didn't skip any rows mistakenly
+ first_hithroughput = df[df["esa_mode"] == 1].iloc[0]
+ assert first_hithroughput["incident_E-Step"] == 1
+ assert first_hithroughput["Observed_E-Step"] == 1
+
+
+def test_read_efficiency_factor():
+ ancillary_file = (
+ ANCILLARY_DIR / "imap_lo_efficiency-factor-small_20250101_20270101_v001.csv"
+ )
+ df = lo_ancillary.read_ancillary_file(ancillary_file)
+ assert len(df) == 31
+ assert "Comments" in df.columns
+
+ # spot check the first row
+ first_row = df.iloc[0]
+ np.testing.assert_array_equal(
+ first_row,
+ np.array(
+ [
+ pd.Timestamp("2025-01-01"),
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0,
+ "Hi Track HiThr",
+ ],
+ dtype=object,
+ ),
+ )
+
+ # spot check the different row
+ lo_track_hithr = df[df["Comments"] == "Lo Track HiThr"].iloc[0]
+ np.testing.assert_array_equal(
+ lo_track_hithr,
+ np.array(
+ [
+ pd.Timestamp("2025-01-22"),
+ 0.93,
+ 0.93,
+ 0.93,
+ 0.93,
+ 0.93,
+ 0.92,
+ 0.92,
+ "Lo Track HiThr",
+ ],
+ dtype=object,
+ ),
+ )
+
+
+def test_read_sweep_table():
+ ancillary_file = (
+ ANCILLARY_DIR / "imap_lo_sweep-table-small_20250101_20260301_v001.csv"
+ )
+ df = lo_ancillary.read_ancillary_file(ancillary_file)
+ assert len(df) == 11
+
+ # spot check the first row
+ np.testing.assert_array_equal(
+ df.iloc[0],
+ np.array(
+ [
+ pd.Timestamp("2024-01-01"),
+ "ENA",
+ "Nominal Mode",
+ 469024800,
+ 469084200,
+ "Lo",
+ 20,
+ "HiRes",
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ ],
+ dtype=object,
+ ),
+ )
+
+
+def test_read_esa_mode_lut():
+ ancillary_file = ANCILLARY_DIR / "imap_lo_esa-mode-lut_v001.csv"
+ df = lo_ancillary.read_ancillary_file(ancillary_file)
+ assert len(df) == 112
+ assert "ESA_Mode" in df.columns
+ # The first 36 rows are ESA mode 0 (HiRes), the second 36 are ESA mode 1 (HiThr)
+ np.testing.assert_array_equal(
+ df.iloc[0],
+ np.array([0, 1, 1, 61.9, 30.5, 66, 67, "HiThr"], dtype=object),
+ )
+
+
+def test_read_pointing_file():
+ ancillary_file = (
+ ANCILLARY_DIR / "imap_lo_pointing-file-small_20250101_20271231_v001.csv"
+ )
+ df = lo_ancillary.read_ancillary_file(ancillary_file)
+ assert len(df) == 5
+
+ np.testing.assert_array_equal(
+ df.iloc[0], np.array([pd.Timestamp("2025-01-01"), 4, 105], dtype=object)
+ )
+
+
+def test_read_pointing_index_file():
+ ancillary_file = ANCILLARY_DIR / "imap_lo_pointing-Index_20250101_20271231_v001.csv"
+ df = lo_ancillary.read_ancillary_file(ancillary_file)
+ assert len(df) == 15
+
+ np.testing.assert_array_equal(
+ df.iloc[0],
+ np.array(
+ [1, 60, 55, 65, pd.Timestamp("2027-07-26"), pd.Timestamp("2027-12-29")],
+ dtype=object,
+ ),
+ )
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 e0694754c5..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,13 +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)
- for dataset, logical_source in zip(output_dataset, 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():
@@ -119,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 0f0eb096bf..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,90 +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
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_set_direction():
- # 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 3804c0e22f..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,33 +7,50 @@
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
@pytest.fixture
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]),
},
@@ -49,11 +68,65 @@ def l1b_de():
@pytest.fixture
-def anc_dependencies():
- anc_dependencies_path = (
- imap_module_directory / "tests/lo/test_anc/imap_lo_goodtimes_20250415_v001.csv"
+def repoint_met():
+ met = np.arange(511000000, 511000000 + 86400 * 5, 86400)
+ return met
+
+
+@pytest.fixture
+def l1b_de_spin():
+ l1b_de = xr.Dataset(
+ {
+ "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", # golden triple - H
+ "111111", # golden triple - O (based on TOF)
+ "111000", # triple
+ "110100", # double
+ "110000", # double
+ ],
+ ),
+ # 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),
+ },
)
- return [str(anc_dependencies_path)]
+ return l1b_de
+
+
+@pytest.fixture
+def anc_dependencies():
+ 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
@@ -67,108 +140,216 @@ def attr_mgr():
@pytest.fixture
def counts():
"""Fixture for initial counts."""
- return np.zeros((1, 7, 3600, 40))
+ 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
-def test_lo_l1c(l1b_de, anc_dependencies):
- # Arrange
- data = {"imap_lo_l1b_de": l1b_de}
+@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),
+ }
+ )
- expected_logical_source = "imap_lo_l1c_pset"
- # Act
- output_dataset = lo_l1c(data, anc_dependencies)
- # Assert
- assert expected_logical_source == output_dataset[0].attrs["Logical_source"]
+@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,
+ use_fake_spin_data_for_time,
+ repoint_met,
+):
+ # Arrange
+ 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
-def test_initialize_pset(l1b_de, attr_mgr):
- # Arrange
- logical_source = "imap_lo_l1c_pset"
- expected_epoch = 7.9794907049e17
+ mock_add_spacecraft_position_and_velocity_to_pset.side_effect = mock_add_sc_pos_vel
+ expected_logical_source = "imap_lo_l1c_pset"
# Act
- pset = initialize_pset(l1b_de, attr_mgr, logical_source)
+ output_dataset = lo_l1c(data, anc_dependencies)[0]
# Assert
- assert pset.attrs["Logical_source"] == logical_source
- np.testing.assert_array_equal(pset["epoch"], expected_epoch)
+ 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_filter_goodtimes(l1b_de, anc_dependencies):
+def test_filter_goodtimes():
# Arrange
- l1b_de_with_badtimes = xr.Dataset(
+ event_mets = [473389199, 473389200, 473389201, 473389202, 473389203, 473407619]
+ l1b_de_all = 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]),
+ "spin_bin": ("epoch", [1900, 2000, 3000, 3000, 3000, 3000]),
},
- coords={
- "epoch": [
- 7.9794907049e17,
- 7.9794907153e17,
- 7.9794907254e17,
- 7.9794907354e17,
- 7.9794907454e17,
- 8.74117692184e17,
- ],
+ 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)},
)
- l1b_de_no_badtimes_expected = l1b_de.copy()
+
+ # 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
- l1b_no_badtimes = filter_goodtimes(l1b_de_with_badtimes, anc_dependencies)
+ result = filter_goodtimes(l1b_de_all, goodtimes_ds)
# Assert
- xr.testing.assert_equal(l1b_no_badtimes, l1b_de_no_badtimes_expected)
+ xr.testing.assert_equal(result, expected)
+
+
+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
+ # 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
+ output_dataset = lo_l1c(data, anc_dependencies)[0]
+
+ # Assert
+ 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)
@@ -209,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((1, 7, 3600, 40), 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
+ representative_spins = get_representative_spin_times(
+ pointing_start_met, pointing_end_met, n_spins=5
+ )
+
+ # Assert
+ 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
- exposure_times = calculate_exposure_times(counts, l1b_de)
+ 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
- np.testing.assert_allclose(
- exposure_times,
- expected_exposure_times,
- atol=1e-2,
+ 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 de60ae226e..3422f20704 100644
--- a/imap_processing/tests/lo/test_lo_l2.py
+++ b/imap_processing/tests/lo/test_lo_l2.py
@@ -1,170 +1,2847 @@
+"""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.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,
+ N_SPIN_ANGLE_BINS,
+ OFF_ANGLE_BIN_CENTERS,
+ PSET_DIMS,
+ PSET_SHAPE,
+ 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_rect_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((1, 7, 3600, 40))
- 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_factor = np.full(PSET_SHAPE, 0.5)
- exposure_time = np.full((1, 7, 3600, 40), 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"
+ )
+ 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"), h_counts),
- "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,
),
+ "hae_longitude": (("epoch", "spin_angle", "off_angle"), hae_longitude),
+ "hae_latitude": (("epoch", "spin_angle", "off_angle"), hae_latitude),
+ },
+ 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 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],
- "energy": [i for i in range(1, 8)],
- "longitude": [i for i in range(3600)],
- "latitude": [i for i in range(40)],
+ "esa_energy_step": ESA_ENERGY_STEPS,
+ "spin_angle": SPIN_ANGLE_BIN_CENTERS,
+ "off_angle": OFF_ANGLE_BIN_CENTERS,
},
)
return dataset
@pytest.fixture
-def map():
- fake_field = np.zeros((1, 7, 60, 30))
- exposure_time = np.full((1, 7, 60, 30), 0.5)
+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": [i for i in range(1, 8)],
+ "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
-@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_project_pset_to_rect_map(pset):
- # Act
- lo_rect_map = project_pset_to_rect_map([pset], 6, geometry.SpiceFrame.ECLIPJ2000)
- assert lo_rect_map.spacing_deg == 6
- assert lo_rect_map.spice_reference_frame == geometry.SpiceFrame.ECLIPJ2000
- assert lo_rect_map.num_points == 1800
+ # 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),
+ }
-@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_calculate_rates():
- # Arrange
- counts = np.zeros((1, 7, 1800))
- counts[0, 0, 0] = 1
- counts[0, 0, 1] = 2
+ # 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)
- exposure_time = np.full((1, 7, 1800), 0.5)
+ 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
- expected_rates = np.zeros((1, 7, 1800))
- expected_rates[0, 0, 0] = 2
- expected_rates[0, 0, 1] = 4
- # Act
- h_rate = calculate_rates(counts, exposure_time)
+@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
- np.testing.assert_array_equal(h_rate, expected_rates)
+@pytest.fixture
+def sample_geometric_factor_data():
+ """Create sample geometric factor data for testing."""
+ h_gf_data = []
+ o_gf_data = []
-@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
+ 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),
+ }
+ )
- expected_fluxes = np.zeros((1, 7, 1800))
- expected_fluxes[0, 0, 0] = 2
- expected_fluxes[0, 1, 0] = 6
+ 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),
+ }
+ )
- # Act
- flux = calculate_fluxes(rates)
+ return pd.DataFrame(h_gf_data), pd.DataFrame(o_gf_data)
- # Assert
- np.testing.assert_array_equal(flux, expected_fluxes)
+@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
-@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_lo_l2(pset):
- # Arrange
- pset = {"imap_lo_l1c_pset": [pset]}
-
- # Act
- hflux_map = lo_l2(pset, [])
-
- # 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",
+ 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),
+ }
+ )
+
+ # 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,
+ )
+
+ # 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,
+ )
+
+ return dataset
+
+
+@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)
+
+ 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
+
+ # 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
+ )
- # Assert
- for field, attr_name in map_fields.items():
- assert updated_map[field].attrs == attr_mgr.get_variable_attributes(
- attr_name, check_schema=False
+ 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_decom.py b/imap_processing/tests/mag/test_mag_decom.py
index f8e584c4cb..a420da5f83 100644
--- a/imap_processing/tests/mag/test_mag_decom.py
+++ b/imap_processing/tests/mag/test_mag_decom.py
@@ -127,7 +127,7 @@ def test_mag_raw_cdf_generation(cdf_attrs):
def test_comparison():
l0_args = [f.name for f in fields(MagL0)][2:-1]
values = np.zeros(len(l0_args), dtype=int)
- attrs = dict(zip(l0_args, values))
+ attrs = dict(zip(l0_args, values, strict=False))
attrs["VECTORS"] = np.array([1.0, 2.0, 3.0, 4.0])
attrs["SHCOARSE"] = 1234
l0_match = MagL0(
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 8b8c20c4cd..2ebe5efe76 100644
--- a/imap_processing/tests/mag/test_mag_l1d.py
+++ b/imap_processing/tests/mag/test_mag_l1d.py
@@ -1,10 +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.mag.constants import DataMode
+from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes
+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
@@ -50,12 +55,13 @@ def mag_l1d_test_class(mag_test_l1d_data):
l1d.quality_flags = np.zeros(len(fake_data["epoch"].data))
l1d.quality_bitmask = np.zeros(len(fake_data["epoch"].data))
l1d.data_mode = DataMode.BURST
- l1d.magi_epoch = fake_data["epoch"].data
- l1d.magi_vectors = fake_data["vectors"].data[:, :3]
+ l1d.magi_epoch = fake_data["epoch"].data + 1
+ l1d.magi_vectors = fake_data["vectors"].data[:, :3] + 10
l1d.magi_range = fake_data["vectors"].data[:, 3]
l1d.config = config
l1d.spin_offsets = None
- l1d.magnitude = None
+ l1d.magnitude = np.zeros(len(fake_data["epoch"].data))
+ l1d.frame = ValidFrames.SRF
return l1d
@@ -68,11 +74,7 @@ def test_mag_l1d(mag_test_l1d_data, norm_dataset, furnish_kernels, fake_mag_spin
burst_mago = norm_dataset.copy()
burst_mago.attrs["Logical_source"] = "imap_mag_l1c_burst-mago"
- kernels = [
- "sim_1yr_imap_pointing_frame.bc",
- ]
with (
- furnish_kernels(kernels),
patch(
"imap_processing.mag.l1d.mag_l1d_data.frame_transform",
side_effect=lambda *args, **kwargs: args[1],
@@ -81,15 +83,143 @@ def test_mag_l1d(mag_test_l1d_data, norm_dataset, furnish_kernels, fake_mag_spin
"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 = mag_l1d(
[norm_dataset, norm_magi, burst_magi, burst_mago],
mag_test_l1d_data,
np.datetime64("2000-01-01"),
)
+ # 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 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
+
+
+@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", "")
+ ]
- assert len(l1d) == 4
- assert "vectors" in l1d[0].data_vars
+ # 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():
@@ -102,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
)
@@ -110,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
)
@@ -120,54 +250,81 @@ def test_offset_vector():
def test_calculate_spin_offsets(
mag_l1d_test_class, fake_mag_spin_data, furnish_kernels
):
+ # Expected to fail, need to merge spice fix
x_vectors = np.arange(1, 156)
y_vectors = np.arange(156, 1, -1)
mag_l1d_test_class.vectors[:, 0] = x_vectors
mag_l1d_test_class.vectors[:, 1] = y_vectors
mag_l1d_test_class.frame = ValidFrames.SRF
+ mag_l1d_test_class.epoch = mag_l1d_test_class.epoch * 1e9
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",
]
# Spins have a length of 15
mag_l1d_test_class.config.spin_count_calibration = 2
- with furnish_kernels(kernels):
+ with (
+ furnish_kernels(kernels),
+ patch(
+ "imap_processing.mag.l1d.mag_l1d_data.ttj2000ns_to_met",
+ side_effect=lambda *args, **kwargs: args[0] / 1e9,
+ ),
+ ):
offsets = mag_l1d_test_class.calculate_spin_offsets()
- expected_epochs = [15, 45, 90, 150]
+ expected_epochs = np.array([15.0, 45.0, 75.0, 105.0, 135.0]) * 1e9
assert np.array_equal(offsets["epoch"].data, expected_epochs)
- # pull out the valid full spins from the test data (last few are fudging to get a
- # chunk from 150-155)
- valid_spins = [
- [15, 30],
- [30, 45],
- [45, 60],
- [75, 90],
- [90, 105],
- [135, 150],
- [150, 155],
- [155, 155],
- ]
-
+ indices_to_average = [[15, 45], [45, 75], [75, 105], [105, 135], [135, 150]]
expected_x_avg = []
expected_y_avg = []
- for index in range(0, len(valid_spins), 2):
- x_spin = x_vectors[valid_spins[index][0] : valid_spins[index + 1][1]]
- expected_x_avg.append(np.nanmean(x_spin))
- y_spin = y_vectors[valid_spins[index][0] : valid_spins[index + 1][1]]
- expected_y_avg.append(np.nanmean(y_spin))
+ for start_index, end_index in indices_to_average:
+ expected_x_avg.append(np.nanmean(x_vectors[start_index:end_index]))
+ expected_y_avg.append(np.nanmean(y_vectors[start_index:end_index]))
np.testing.assert_allclose(offsets["x_offset"].data, expected_x_avg)
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)
@@ -216,9 +373,19 @@ def test_calculate_gradiometry_offsets():
assert np.array_equal(grad_ds["epoch"].data, mago_epoch)
assert np.array_equal(grad_ds["gradiometer_offsets"].data.shape, mago_vectors.shape)
-
assert np.allclose(grad_ds["gradiometer_offsets"].data, np.full((10, 3), -5.0))
+ # Test new fields
+ expected_magnitude = np.linalg.norm(np.full((10, 3), -5.0), axis=1)
+ assert np.allclose(grad_ds["gradiometer_offset_magnitude"].data, expected_magnitude)
+ assert np.array_equal(
+ grad_ds["quality_flags"].data, np.zeros(10)
+ ) # All below default threshold
+
+ # Test shapes
+ assert grad_ds["gradiometer_offset_magnitude"].data.shape == (10,)
+ assert grad_ds["quality_flags"].data.shape == (10,)
+
def test_apply_gradiometry_offsets():
vectors = np.ones((5, 3)) * 10
@@ -233,3 +400,309 @@ def test_apply_gradiometry_offsets():
)
assert np.allclose(output[0] - vectors[0], np.dot([-1, -1, -2], gradiometer_factor))
+
+
+def test_quality_flags_with_threshold():
+ """Test that quality flags are set correctly when magnitude exceeds threshold."""
+ mago_vectors = np.array(
+ [[10, 10, 10], [10, 10, 10], [1, 1, 1], [1, 1, 1], [10, 10, 10]]
+ )
+ mago_epoch = np.arange(5) * 1e9
+
+ magi_vectors = np.array([[5, 5, 5], [5, 5, 5], [0, 0, 0], [0, 0, 0], [5, 5, 5]])
+ magi_epoch = mago_epoch + 500
+
+ # Set threshold so that only the large differences trigger quality flags
+ # Magnitude for [5,5,5] difference is ~8.66, for [1,1,1] difference is ~1.73
+ quality_threshold = 5.0
+
+ grad_ds = MagL1d.calculate_gradiometry_offsets(
+ mago_vectors, mago_epoch, magi_vectors, magi_epoch, quality_threshold
+ )
+
+ # First, second, and fifth vectors should exceed threshold (magnitude ~8.66)
+ # Third and fourth vectors should not exceed threshold (magnitude ~1.73)
+ expected_flags = np.array([1, 1, 0, 0, 1])
+ assert np.array_equal(grad_ds["quality_flags"].data, expected_flags)
+
+ # Test shapes for 5 vectors
+ assert grad_ds["gradiometer_offset_magnitude"].data.shape == (5,)
+ assert grad_ds["quality_flags"].data.shape == (5,)
+
+
+def test_skip_gradiometry(norm_dataset, mag_test_l1d_data, fake_mag_spin_data):
+ # Set up test data with all_vectors_primary = 0 for MAGO dataset
+ norm_magi = norm_dataset.copy()
+ norm_magi.attrs["Logical_source"] = "imap_mag_l1c_norm-magi"
+ burst_magi = norm_dataset.copy()
+ burst_magi.attrs["Logical_source"] = "imap_mag_l1c_burst-magi"
+ burst_mago = norm_dataset.copy()
+ burst_mago.attrs["Logical_source"] = "imap_mag_l1c_burst-mago"
+
+ # Set all_vectors_primary = 0 for MAGO dataset to disable gradiometry
+ norm_dataset.attrs["all_vectors_primary"] = 0
+ norm_magi.attrs["all_vectors_primary"] = 1 # MAGI doesn't matter for this check
+ burst_mago.attrs["all_vectors_primary"] = 0
+ burst_magi.attrs["all_vectors_primary"] = 1
+
+ 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] / 1e9,
+ ),
+ patch.object(MagL1d, "calculate_gradiometry_offsets") as mock_calc,
+ patch.object(MagL1d, "apply_gradiometry_offsets") as mock_apply,
+ ):
+ mag_l1d(
+ [norm_dataset, norm_magi, burst_magi, burst_mago],
+ mag_test_l1d_data,
+ np.datetime64("2000-01-01"),
+ )
+
+ # Verify the gradiometry methods were never called
+ mock_calc.assert_not_called()
+ mock_apply.assert_not_called()
+
+
+def test_spin_offset_gap_handling():
+ """Test improved gap handling in spin calculation."""
+ # Test the logic for handling data gaps
+ # Create a mock scenario with gaps in spin data
+
+ # Mock spin data with a gap
+ spin_phase = np.array([0.1, 0.2, 0.3, np.nan, np.nan, np.nan, 0.1, 0.2, 0.3])
+
+ # Find transitions from nan to number and vice versa
+ nan_to_number = np.where(np.diff(np.isnan(spin_phase)) != 0)[0] + 1
+
+ # Should detect gap start at index 3 and gap end at index 6
+ expected_transitions = np.array([3, 6])
+ assert np.array_equal(nan_to_number, expected_transitions)
+
+ # Test that we can identify gaps that span multiple spins
+ gap_start_idx, gap_end_idx = 3, 6
+ assert gap_end_idx > gap_start_idx # Basic gap detection works
+
+
+@patch("imap_processing.mag.imap_mag_sdc_configuration_v001.ALWAYS_OUTPUT_MAGO", False)
+def test_mago_magi_swap_functionality(mag_l1d_test_class):
+ """Test MAGO/MAGI swap functionality when ALWAYS_OUTPUT_MAGO is False."""
+ mago_vectors = mag_l1d_test_class.vectors.copy()
+ mago_epoch = mag_l1d_test_class.epoch.copy()
+ magi_vectors = mag_l1d_test_class.magi_vectors.copy()
+ magi_epoch = mag_l1d_test_class.magi_epoch.copy()
+
+ with patch(
+ "imap_processing.mag.l1d.mag_l1d_data.MagL2L1dBase.truncate_to_24h",
+ return_value=None,
+ ):
+ # Call generate_dataset (this should swap to use MAGI data)
+ attributes = ImapCdfAttributes()
+ attributes.add_instrument_global_attrs("mag")
+ attributes.add_instrument_variable_attrs("mag", "l2")
+
+ result = mag_l1d_test_class.generate_dataset(
+ attributes, np.datetime64("2000-01-01")
+ )
+
+ # After generate_dataset, original vectors should be restored
+ 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[mag_l1d_test_class.frame.var_name].data, magi_vectors)
+ assert np.array_equal(result["epoch"].data, magi_epoch)
+
+
+@patch("imap_processing.mag.imap_mag_sdc_configuration_v001.ALWAYS_OUTPUT_MAGO", True)
+def test_mago_magi_no_swap_functionality(mag_l1d_test_class):
+ """Test MAGO/MAGI swap functionality when ALWAYS_OUTPUT_MAGO is False."""
+ mago_vectors = mag_l1d_test_class.vectors.copy()
+ mago_epoch = mag_l1d_test_class.epoch.copy()
+
+ with patch(
+ "imap_processing.mag.l1d.mag_l1d_data.MagL2L1dBase.truncate_to_24h",
+ return_value=None,
+ ):
+ # Call generate_dataset (this should swap to use MAGI data)
+ attributes = ImapCdfAttributes()
+ attributes.add_instrument_global_attrs("mag")
+ attributes.add_instrument_variable_attrs("mag", "l2")
+
+ result = mag_l1d_test_class.generate_dataset(
+ attributes, np.datetime64("2000-01-01")
+ )
+
+ # After generate_dataset, original vectors should be restored
+ 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[mag_l1d_test_class.frame.var_name].data, mago_vectors)
+ assert np.array_equal(result["epoch"].data, mago_epoch)
+
+
+def test_enhanced_gradiometry_with_quality_flags_detailed():
+ """Test enhanced gradiometry calculation with quality flags and magnitude."""
+ # Test data with known differences
+ mago_vectors = np.array(
+ [
+ [10, 10, 10], # Large difference case
+ [1, 1, 1], # Small difference case
+ [5, 5, 5], # Medium difference case
+ ]
+ )
+ mago_epoch = np.array([0, 1000000000, 2000000000]) # 1 second intervals
+
+ magi_vectors = np.array(
+ [
+ [5, 5, 5], # After interpolation: actual offsets will be computed
+ [0.5, 0.5, 0.5], # based on linear interpolation to MAGo timestamps
+ [3, 3, 3], # See expected_offsets calculation below
+ ]
+ )
+ magi_epoch = mago_epoch + 500000000 # 0.5 second offset
+
+ # Set threshold so medium and large differences exceed it
+ quality_threshold = 3.5
+
+ grad_ds = MagL1d.calculate_gradiometry_offsets(
+ mago_vectors, mago_epoch, magi_vectors, magi_epoch, quality_threshold
+ )
+
+ # Test basic functionality
+ assert "gradiometer_offsets" in grad_ds.data_vars
+ assert "gradiometer_offset_magnitude" in grad_ds.data_vars
+ assert "quality_flags" in grad_ds.data_vars
+
+ # Test shapes
+ assert grad_ds["gradiometer_offsets"].shape == (3, 3)
+ assert grad_ds["gradiometer_offset_magnitude"].shape == (3,)
+ assert grad_ds["quality_flags"].shape == (3,)
+
+ # Test calculated values
+ # After interpolation, MAGi values at MAGo timestamps:
+ # t=0: [7.25, 7.25, 7.25], t=1: [2.75, 2.75, 2.75], t=2: [1.75, 1.75, 1.75]
+ # Offsets = MAGi_interpolated - MAGo
+ expected_offsets = np.array(
+ [[-2.75, -2.75, -2.75], [1.75, 1.75, 1.75], [-3.25, -3.25, -3.25]]
+ )
+ expected_magnitudes = np.linalg.norm(expected_offsets, axis=1)
+ expected_flags = np.array([1, 0, 1])
+
+ np.testing.assert_allclose(
+ grad_ds["gradiometer_offsets"].data, expected_offsets, rtol=1e-10
+ )
+ np.testing.assert_allclose(
+ 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 7c7c49a962..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.usefixtures("_download_test_data")
+@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(
@@ -317,7 +334,7 @@ def test_mag_l1c_validation(test_number, sensor):
@pytest.mark.parametrize(("test_number", "mode"), [("021", "burst"), ("022", "norm")])
-@pytest.mark.usefixtures("_download_test_data")
+@pytest.mark.external_test_data
def test_mag_l2_validation(test_number, mode):
source_directory = Path(__file__).parent / "validation" / "L2" / f"T{test_number}"
magi_in = source_directory / f"mag-l1bc-l2-t{test_number}-mago-{mode}-in.csv"
@@ -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-burst-in.csv b/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-burst-in.csv
new file mode 100644
index 0000000000..916ef68508
--- /dev/null
+++ b/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-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,-14.001918777,27.11799801333,-19.46673193014,2,1,18
+2025-03-11T12:38:02.141052,479392685,1052,171,-14.3313756894,27.852590092635,-20.021108062275,2,1,18
+2025-03-11T12:38:02.266052,479392685,1052,171,-14.61847385592,28.48092840297,-20.542492009485,2,1,18
+2025-03-11T12:38:02.391052,479392685,1052,171,-14.86321327656,29.049182503785,-20.989546056135,2,1,18
+2025-03-11T12:38:02.516052,479392685,1052,171,-15.10324616988,29.56664300229,-21.35778025455,2,1,18
+2025-03-11T12:38:02.641052,479392685,1052,171,-15.28209420804,29.97320442822,-21.679096832325,2,1,18
+2025-03-11T12:38:02.766052,479392685,1052,171,-15.4374096096,30.3104760804,-21.92607559296,2,1,18
+2025-03-11T12:38:02.891052,479392685,1052,171,-15.5550727926,30.57381974214,-22.126382341605,2,1,18
+2025-03-11T12:38:03.016052,479392685,1052,171,-15.63508375704,30.749384545605,-22.27070384298,2,1,18
+2025-03-11T12:38:03.141052,479392685,1052,171,-15.67744250292,30.827936578905,-22.34513107854,2,1,18
+2025-03-11T12:38:03.266052,479392685,1052,171,-15.68214903024,30.851028445545,-22.36374340308,2,1,18
+2025-03-11T12:38:03.391052,479392685,1052,171,-15.65390986632,30.78173158488,-22.30787586627,2,1,18
+2025-03-11T12:38:03.516052,479392685,1052,171,-15.5786054292,30.620024736165,-22.17749790492,2,1,18
+2025-03-11T12:38:03.641052,479392685,1052,171,-15.4844748828,30.38441824467,-21.986628331455,2,1,18
+2025-03-11T12:38:03.766052,479392685,1052,171,-15.3432790632,30.084103500795,-21.753735155055,2,1,18
+2025-03-11T12:38:03.891052,479392685,1052,171,-15.178550607,29.691414203445,-21.44176237575,2,1,18
+2025-03-11T12:38:04.016052,479392685,1052,171,-14.97146340492,29.220172872795,-21.083083062975,2,1,18
+2025-03-11T12:38:04.141052,479392685,1052,171,-14.72201745696,28.679613420735,-20.654645299155,2,1,18
+2025-03-11T12:38:04.266052,479392685,1052,171,-14.43962581776,28.03743132948,-20.18401982559,2,1,18
+2025-03-11T12:38:04.391052,479392685,1052,171,-14.13840806928,27.33520046328,-19.629875156085,2,1,18
+2025-03-11T12:38:04.516052,479392685,1052,171,-13.80895115688,26.57752360425,-19.01993595102,2,1,18
+2025-03-11T12:38:04.641052,479392685,1052,171,-13.44184202592,25.732067886945,-18.372491966745,2,1,18
+2025-03-11T12:38:04.766052,479392685,1052,171,-13.0370806764,24.79421635542,-17.655178050405,2,1,18
+2025-03-11T12:38:04.891052,479392685,1052,171,-12.6370258542,23.814819307305,-16.89607426491,2,1,18
+2025-03-11T12:38:05.016052,479392685,1052,171,-12.16166659488,22.7891393091,-16.0949830851,2,1,18
+2025-03-11T12:38:05.141052,479392685,1052,171,-11.67689428092,21.689573841945,-15.24728101968,2,1,18
+2025-03-11T12:38:05.266052,479392685,1052,171,-11.16858933036,20.534569468875,-14.357654957475,2,1,18
+2025-03-11T12:38:05.391052,479392685,1052,171,-10.63204521588,19.31026823514,-13.42140159249,2,1,18
+2025-03-11T12:38:05.516052,479392685,1052,171,-10.06726193748,18.03513796452,-12.447858493755,2,1,18
+2025-03-11T12:38:05.641052,479392685,1052,171,-9.48835907712,16.750752521265,-11.41879476015,2,1,18
+2025-03-11T12:38:05.766052,479392685,1052,171,-8.89063010748,15.406318303065,-10.3662733518,2,1,18
+2025-03-11T12:38:05.891052,479392685,1052,171,-8.28819461052,14.00647352661,-9.28572904863,2,1,18
+2025-03-11T12:38:06.015976,479392689,1047,172,-7.67634605892,12.560445016875,-8.17720033041,2,1,18
+2025-03-11T12:38:06.140976,479392689,1047,172,-7.04096487072,11.09129629284,-7.05925877076,2,1,18
+2025-03-11T12:38:06.265976,479392689,1047,172,-6.38675757324,9.622119221145,-5.9135557581,2,1,18
+2025-03-11T12:38:06.390976,479392689,1047,172,-5.72784374844,8.115999414975,-4.735307068605,2,1,18
+2025-03-11T12:38:06.515976,479392689,1047,172,-5.059516869,6.60524847903,-3.5570136699,2,1,18
+2025-03-11T12:38:06.640976,479392689,1047,172,-4.37236388028,5.057533547865,-2.369244616245,2,1,18
+2025-03-11T12:38:06.765976,479392689,1047,172,-3.68050436424,3.500577617895,-1.158316122285,2,1,18
+2025-03-11T12:38:06.890976,479392689,1047,172,-3.00276443016,1.920558168945,0.071183945295,2,1,18
+2025-03-11T12:38:07.015976,479392689,1047,172,-2.32502449608,0.359006543775,1.291346443845,2,1,18
+2025-03-11T12:38:07.140976,479392689,1047,172,-1.6237519254,-1.207197471915,2.50696409778,2,1,18
+2025-03-11T12:38:07.265976,479392689,1047,172,-0.95071851864,-2.764125054225,3.71785184082,2,1,18
+2025-03-11T12:38:07.390976,479392689,1047,172,-0.26827205724,-4.31644985442,4.914875274525,2,1,18
+2025-03-11T12:38:07.515976,479392689,1047,172,0.41417440416,-5.86415769867,6.09339390642,2,1,18
+2025-03-11T12:38:07.640976,479392689,1047,172,1.06367517432,-7.356412463175,7.24844863413,2,1,18
+2025-03-11T12:38:07.765976,479392689,1047,172,1.72258899912,-8.83944748962,8.408095186815,2,1,18
+2025-03-11T12:38:07.890976,479392689,1047,172,2.38150282392,-10.30863164823,9.53994803616,2,1,18
+2025-03-11T12:38:08.015976,479392689,1047,172,2.99335137552,-11.74080929013,10.65764398716,2,1,18
+2025-03-11T12:38:08.140976,479392689,1047,172,3.60519992712,-13.11758346069,11.724226645995,2,1,18
+2025-03-11T12:38:08.265976,479392689,1047,172,4.19351584212,-14.48047132884,12.776825013885,2,1,18
+2025-03-11T12:38:08.390976,479392689,1047,172,4.7771252298,-15.787948638735,13.782920018895,2,1,18
+2025-03-11T12:38:08.515976,479392689,1047,172,5.32308239892,-17.03996578197,14.760920814975,2,1,18
+2025-03-11T12:38:08.640976,479392689,1047,172,5.84080040412,-18.23191997643,15.70620332682,2,1,18
+2025-03-11T12:38:08.765976,479392689,1047,172,6.35851840932,-19.419257214945,16.605260334765,2,1,18
+2025-03-11T12:38:08.890976,479392689,1047,172,6.85270377792,-20.532687723765,17.43919542585,2,1,18
+2025-03-11T12:38:09.015976,479392689,1047,172,7.33747609188,-21.57684971958,18.24964455015,2,1,18
+2025-03-11T12:38:09.140976,479392689,1047,172,7.76106355068,-22.55628220227,19.018039508325,2,1,18
+2025-03-11T12:38:09.265976,479392689,1047,172,8.14699879092,-23.46178669452,19.71204175242,2,1,18
+2025-03-11T12:38:09.390976,479392689,1047,172,8.52822750384,-24.311880628515,20.38264121871,2,1,18
+2025-03-11T12:38:09.515976,479392689,1047,172,8.86709747088,-25.078805573265,20.97878911569,2,1,18
+2025-03-11T12:38:09.640976,479392689,1047,172,9.17302174668,-25.767192658545,21.52825085466,2,1,18
+2025-03-11T12:38:09.765976,479392689,1047,172,9.45070685856,-26.409367662885,22.017346608555,2,1,18
+2025-03-11T12:38:09.890976,479392689,1047,172,9.70485933384,-26.94993420186,22.445794560105,2,1,18
+2025-03-11T12:38:10.015930,479392693,1044,173,9.91194653592,-27.4304094444,22.809142657395,2,1,18
+2025-03-11T12:38:10.140930,479392693,1044,173,10.10491415604,-27.82314126324,23.107316212035,2,1,18
+2025-03-11T12:38:10.265930,479392693,1044,173,10.24140344832,-28.155767611815,23.358850005015,2,1,18
+2025-03-11T12:38:10.390930,479392693,1044,173,10.34024052204,-28.382147278335,23.545060981695,2,1,18
+2025-03-11T12:38:10.515930,479392693,1044,173,10.41554495916,-28.548471082995,23.66160292575,2,1,18
+2025-03-11T12:38:10.640930,479392693,1044,173,10.44378412308,-28.622384899605,23.71749479631,2,1,18
+2025-03-11T12:38:10.765930,479392693,1044,173,10.4249580138,-28.60850568411,23.703520693095,2,1,18
+2025-03-11T12:38:10.890930,479392693,1044,173,10.39201232256,-28.50226608897,23.628967830495,2,1,18
+2025-03-11T12:38:11.015930,479392693,1044,173,10.31670788544,-28.322091416475,23.498492534145,2,1,18
+2025-03-11T12:38:11.140930,479392693,1044,173,10.20845775708,-28.067995840455,23.29825482846,2,1,18
+2025-03-11T12:38:11.265930,479392693,1044,173,10.07667499212,-27.73075962285,23.01898618737,2,1,18
+2025-03-11T12:38:11.390930,479392693,1044,173,9.89782695396,-27.30573037314,22.71143262564,2,1,18
+2025-03-11T12:38:11.515930,479392693,1044,173,9.6719136426,-26.820609826995,22.334159092635,2,1,18
+2025-03-11T12:38:11.640930,479392693,1044,173,9.42717422196,-26.22465399051,21.88233892647,2,1,18
+2025-03-11T12:38:11.765930,479392693,1044,173,9.14478258276,-25.582471899255,21.3793726338,2,1,18
+2025-03-11T12:38:11.890930,479392693,1044,173,8.80591261572,-24.85709955801,20.825024793705,2,1,18
+2025-03-11T12:38:12.015930,479392693,1044,173,8.44351001208,-24.071671354905,20.219488389045,2,1,18
+2025-03-11T12:38:12.140930,479392693,1044,173,8.0716943538,-23.20312377096,19.51647114411,2,1,18
+2025-03-11T12:38:12.265930,479392693,1044,173,7.66693300428,-22.26065528349,18.803753011035,2,1,18
+2025-03-11T12:38:12.390930,479392693,1044,173,7.22922596352,-21.262733716275,18.030610037655,2,1,18
+2025-03-11T12:38:12.515930,479392693,1044,173,6.78210586812,-20.200160592,17.192424378105,2,1,18
+2025-03-11T12:38:12.640930,479392693,1044,173,6.27380091756,-19.077474910545,16.335309471255,2,1,18
+2025-03-11T12:38:12.765930,479392693,1044,173,5.765495967,-17.90861966964,15.41788970571,2,1,18
+2025-03-11T12:38:12.890930,479392693,1044,173,5.21953879788,-16.66121948235,14.472254062485,2,1,18
+2025-03-11T12:38:13.015930,479392693,1044,173,4.65004899216,-15.39993299265,13.494153660255,2,1,18
+2025-03-11T12:38:13.140930,479392693,1044,173,4.07585265912,-14.101703768475,12.46502711313,2,1,18
+2025-03-11T12:38:13.265930,479392693,1044,173,3.46400410752,-12.734163509805,11.398493121795,2,1,18
+2025-03-11T12:38:13.390930,479392693,1044,173,2.86627513788,-11.315857996485,10.299381203295,2,1,18
+2025-03-11T12:38:13.515930,479392693,1044,173,2.24972005896,-9.88367326767,9.172434830535,2,1,18
+2025-03-11T12:38:13.640930,479392693,1044,173,1.60492581612,-8.396042546025,8.05899567744,2,1,18
+2025-03-11T12:38:13.765930,479392693,1044,173,0.96013157328,-6.903794868435,6.89471090343,2,1,18
+2025-03-11T12:38:13.890930,479392693,1044,173,0.27768511188,-5.393022671745,5.716386941535,2,1,18
+2025-03-11T12:38:14.015869,479392697,1040,174,-0.4000548222,-3.8545558263,4.52868693084,2,1,18
+2025-03-11T12:38:14.140869,479392697,1040,174,-1.0825012836,-2.302231026105,3.331663497135,2,1,18
+2025-03-11T12:38:14.265869,479392697,1040,174,-1.76965427232,-0.76375000683,2.139322993965,2,1,18
+2025-03-11T12:38:14.390869,479392697,1040,174,-2.45680726104,0.81628361595,0.919042784955,2,1,18
+2025-03-11T12:38:14.515869,479392697,1040,174,-3.14396024976,2.382466370895,-0.28730407176,2,1,18
+2025-03-11T12:38:14.640869,479392697,1040,174,-3.81699365652,3.94401090915,-1.50745638258,2,1,18
+2025-03-11T12:38:14.765869,479392697,1040,174,-4.50414664524,5.47787497248,-2.713632903045,2,1,18
+2025-03-11T12:38:14.890869,479392697,1040,174,-5.19129963396,7.03020685959,-3.91066652448,2,1,18
+2025-03-11T12:38:15.015869,479392697,1040,174,-5.86433304072,8.564049662175,-5.107572247725,2,1,18
+2025-03-11T12:38:15.140869,479392697,1040,174,-6.50912728356,10.047063427875,-6.25794800319,2,1,18
+2025-03-11T12:38:15.265869,479392697,1040,174,-7.14921499908,11.54853793044,-7.408410905925,2,1,18
+2025-03-11T12:38:15.390869,479392697,1040,174,-7.80342229656,12.99463022241,-8.517031313715,2,1,18
+2025-03-11T12:38:15.515869,479392697,1040,174,-8.42939043012,14.399127389385,-9.616131357345,2,1,18
+2025-03-11T12:38:15.640869,479392697,1040,174,-9.04123898172,15.771284604,-10.69192991646,2,1,18
+2025-03-11T12:38:15.765869,479392697,1040,174,-9.6248483694,17.1203145174,-11.71672439328,2,1,18
+2025-03-11T12:38:15.890869,479392697,1040,174,-10.19904470244,18.418543741575,-12.7135101213,2,1,18
+2025-03-11T12:38:16.015869,479392697,1040,174,-10.74500187156,19.67056088481,-13.68227068335,2,1,18
+2025-03-11T12:38:16.140869,479392697,1040,174,-11.26742640408,20.87637303402,-14.61377603313,2,1,18
+2025-03-11T12:38:16.265869,479392697,1040,174,-11.7663183,22.008278453535,-15.49863993411,2,1,18
+2025-03-11T12:38:16.390869,479392697,1040,174,-12.24167755932,23.084744967135,-16.350820072335,2,1,18
+2025-03-11T12:38:16.515869,479392697,1040,174,-12.69350418204,24.10577257482,-17.142595745715,2,1,18
+2025-03-11T12:38:16.640869,479392697,1040,174,-13.11709164084,25.062120277785,-17.887768450065,2,1,18
+2025-03-11T12:38:16.765869,479392697,1040,174,-13.52185299036,25.976887029585,-18.59110034661,2,1,18
+2025-03-11T12:38:16.890869,479392697,1040,174,-13.884255594,26.803867836195,-19.238436808155,2,1,18
+2025-03-11T12:38:17.015869,479392697,1040,174,-14.22312556104,27.570792780945,-19.816104237075,2,1,18
+2025-03-11T12:38:17.140869,479392697,1040,174,-14.52904983684,28.249945954335,-20.33317648944,2,1,18
+2025-03-11T12:38:17.265869,479392697,1040,174,-14.79261536676,28.83669622659,-20.803469207085,2,1,18
+2025-03-11T12:38:17.390869,479392697,1040,174,-15.01852867812,29.35413546435,-21.213253895445,2,1,18
+2025-03-11T12:38:17.515869,479392697,1040,174,-15.21620282556,29.802277841445,-21.57179116401,2,1,18
+2025-03-11T12:38:17.640869,479392697,1040,174,-15.39975739104,30.18114461862,-21.85139087388,2,1,18
+2025-03-11T12:38:17.765869,479392697,1040,174,-15.53624668332,30.467601407745,-22.06572039324,2,1,18
+2025-03-11T12:38:17.890869,479392697,1040,174,-15.63037722972,30.67550616357,-22.23334337913,2,1,18
+2025-03-11T12:38:18.015808,479392701,1036,175,-15.67744250292,30.809468755125,-22.340413626525,2,1,18
+2025-03-11T12:38:18.140808,479392701,1036,175,-15.6962686122,30.864900574125,-22.368467084535,2,1,18
+2025-03-11T12:38:18.265808,479392701,1036,175,-15.68214903024,30.82794366582,-22.33590103224,2,1,18
+2025-03-11T12:38:18.390808,479392701,1036,175,-15.63979028436,30.717072940905,-22.247443109385,2,1,18
+2025-03-11T12:38:18.515808,479392701,1036,175,-15.56448584724,30.532281312465,-22.089222777195,2,1,18
+2025-03-11T12:38:18.640808,479392701,1036,175,-15.42799655496,30.250441479285,-21.884157825615,2,1,18
+2025-03-11T12:38:18.765808,479392701,1036,175,-15.26797462608,29.880844048575,-21.595417487865,2,1,18
+2025-03-11T12:38:18.890808,479392701,1036,175,-15.07500700596,29.441942670285,-21.25541954259,2,1,18
+2025-03-11T12:38:19.015808,479392701,1036,175,-14.85850674924,28.924517606355,-20.85489546372,2,1,18
+2025-03-11T12:38:19.140808,479392701,1036,175,-14.590234692,28.319292423405,-20.393735457375,2,1,18
+2025-03-11T12:38:19.265808,479392701,1036,175,-14.27960388888,27.6401321631,-19.872032900265,2,1,18
+2025-03-11T12:38:19.390808,479392701,1036,175,-13.9548535038,26.89631325882,-19.2991378203,2,1,18
+2025-03-11T12:38:19.515808,479392701,1036,175,-13.6018639548,26.06934662604,-18.651821734215,2,1,18
+2025-03-11T12:38:19.640808,479392701,1036,175,-13.21122218724,25.19615373849,-17.971839989685,2,1,18
+2025-03-11T12:38:19.765808,479392701,1036,175,-12.81587389236,24.239848557015,-17.226728411715,2,1,18
+2025-03-11T12:38:19.890808,479392701,1036,175,-12.3781668516,23.21422525413,-16.44881931882,2,1,18
+2025-03-11T12:38:20.015808,479392701,1036,175,-11.9075141196,22.1331488715,-15.596625034575,2,1,18
+2025-03-11T12:38:20.140808,479392701,1036,175,-11.39920916904,20.991995366265,-14.70707197362,2,1,18
+2025-03-11T12:38:20.265808,479392701,1036,175,-10.88149116384,19.79542421586,-13.789485830115,2,1,18
+2025-03-11T12:38:20.390808,479392701,1036,175,-10.33553399472,18.571108808295,-12.839351738625,2,1,18
+2025-03-11T12:38:20.515808,479392701,1036,175,-9.76133766168,17.26364567223,-11.83789722609,2,1,18
+2025-03-11T12:38:20.640808,479392701,1036,175,-9.177728274,15.92384967072,-10.8223916508,2,1,18
+2025-03-11T12:38:20.765808,479392701,1036,175,-8.589412359,14.55172789068,-9.74202391332,2,1,18
+2025-03-11T12:38:20.890808,479392701,1036,175,-7.96815075276,13.12876998684,-8.647456839435,2,1,18
+2025-03-11T12:38:21.015808,479392701,1036,175,-7.32806303724,11.682698955615,-7.520386526775,2,1,18
+2025-03-11T12:38:21.140808,479392701,1036,175,-6.67856226708,10.21814592678,-6.365477801565,2,1,18
+2025-03-11T12:38:21.265808,479392701,1036,175,-6.00552886032,8.73508963959,-5.210420802705,2,1,18
+2025-03-11T12:38:21.390808,479392701,1036,175,-5.35602809016,7.187431403745,-4.036593601935,2,1,18
+2025-03-11T12:38:21.515808,479392701,1036,175,-4.6829946834,5.648971645215,-2.835043427925,2,1,18
+2025-03-11T12:38:21.640808,479392701,1036,175,-4.00525474932,4.10127088788,-1.62881428167,2,1,18
+2025-03-11T12:38:21.765808,479392701,1036,175,-3.31339523328,2.54431495791,-0.43636625577,2,1,18
+2025-03-11T12:38:21.890808,479392701,1036,175,-2.62624224456,0.968898291075,0.760789034415,2,1,18
+2025-03-11T12:38:22.015732,479392705,1031,176,-1.93438272852,-0.57420677106,1.97626464414,2,1,18
+2025-03-11T12:38:22.140732,479392705,1031,176,-1.26134932176,-2.135751309315,3.18717672093,2,1,18
+2025-03-11T12:38:22.265732,479392705,1031,176,-0.58360938768,-3.669601198815,4.393332865935,2,1,18
+2025-03-11T12:38:22.390732,479392705,1031,176,0.0941305464,-5.18960022048,5.576315424615,2,1,18
+2025-03-11T12:38:22.515732,479392705,1031,176,0.76245742584,-6.71420202426,6.7639220586,2,1,18
+2025-03-11T12:38:22.640732,479392705,1031,176,1.411958196,-8.23877548038,7.92838735659,2,1,18
+2025-03-11T12:38:22.765732,479392705,1031,176,2.0473393842,-9.726392028195,9.060286602285,2,1,18
+2025-03-11T12:38:22.890732,479392705,1031,176,2.6827205724,-11.163222060615,10.1826779427,2,1,18
+2025-03-11T12:38:23.015732,479392705,1031,176,3.30398217864,-12.57232909662,11.267931781305,2,1,18
+2025-03-11T12:38:23.140732,479392705,1031,176,3.92053725756,-13.949110354095,12.33452462787,2,1,18
+2025-03-11T12:38:23.265732,479392705,1031,176,4.50885317256,-15.284296486575,13.363876408185,2,1,18
+2025-03-11T12:38:23.390732,479392705,1031,176,5.07834297828,-16.55019993222,14.360481612225,2,1,18
+2025-03-11T12:38:23.515732,479392705,1031,176,5.6007675108,-17.79294772899,15.33376268514,2,1,18
+2025-03-11T12:38:23.640732,479392705,1031,176,6.118485516,-18.97566801156,16.25589594441,2,1,18
+2025-03-11T12:38:23.765732,479392705,1031,176,6.62208393924,-20.084495738265,17.12216789631,2,1,18
+2025-03-11T12:38:23.890732,479392705,1031,176,7.07861708928,-21.151699992315,17.95115803104,2,1,18
+2025-03-11T12:38:24.015732,479392705,1031,176,7.530443712,-22.149642820275,18.738191918655,2,1,18
+2025-03-11T12:38:24.140732,479392705,1031,176,7.95873769812,-23.115231522045,19.464943010175,2,1,18
+2025-03-11T12:38:24.265732,479392705,1031,176,8.34467293836,-23.98841732268,20.144914566975,2,1,18
+2025-03-11T12:38:24.390732,479392705,1031,176,8.70236901468,-24.77383843887,20.768921251965,2,1,18
+2025-03-11T12:38:24.515732,479392705,1031,176,9.0365324544,-25.4992036932,21.32325890433,2,1,18
+2025-03-11T12:38:24.640732,479392705,1031,176,9.3189240936,-26.159853608235,21.83556276603,2,1,18
+2025-03-11T12:38:24.765732,479392705,1031,176,9.56837004156,-26.746582619745,22.27348410138,2,1,18
+2025-03-11T12:38:24.890732,479392705,1031,176,9.7895768256,-27.240929990865,22.6646564652,2,1,18
+2025-03-11T12:38:25.015732,479392705,1031,176,9.99195750036,-27.68446249893,22.99083876864,2,1,18
+2025-03-11T12:38:25.140732,479392705,1031,176,10.14727290192,-28.026351107055,23.2609424481,2,1,18
+2025-03-11T12:38:25.265732,479392705,1031,176,10.26964261224,-28.2989357676,23.489028754065,2,1,18
+2025-03-11T12:38:25.390732,479392705,1031,176,10.34965357668,-28.492968394845,23.62420735641,2,1,18
+2025-03-11T12:38:25.515732,479392705,1031,176,10.38730579524,-28.58998116501,23.694101622225,2,1,18
+2025-03-11T12:38:25.640732,479392705,1031,176,10.4014253772,-28.608470249535,23.712709988475,2,1,18
+2025-03-11T12:38:25.765732,479392705,1031,176,10.38259926792,-28.55765538648,23.66158027914,2,1,18
+2025-03-11T12:38:25.890732,479392705,1031,176,10.32612094008,-28.405210797315,23.545152087255,2,1,18
+2025-03-11T12:38:26.015655,479392709,1026,177,10.2131642844,-28.17880987005,23.3635306644,2,1,18
+2025-03-11T12:38:26.140655,479392709,1026,177,10.08608804676,-27.86004856314,23.13981095022,2,1,18
+2025-03-11T12:38:26.265655,479392709,1026,177,9.9072400086,-27.458104093155,22.836999174255,2,1,18
+2025-03-11T12:38:26.390655,479392709,1026,177,9.70485933384,-27.0053376732,22.45994691615,2,1,18
+2025-03-11T12:38:26.515655,479392709,1026,177,9.46482644052,-26.48326021875,22.05010733085,2,1,18
+2025-03-11T12:38:26.640655,479392709,1026,177,9.19655438328,-25.845716344185,21.58415687124,2,1,18
+2025-03-11T12:38:26.765655,479392709,1026,177,8.91416274408,-25.15736469348,21.030125953905,2,1,18
+2025-03-11T12:38:26.890655,479392709,1026,177,8.56117319508,-24.35809979637,20.42915704047,2,1,18
+2025-03-11T12:38:27.015655,479392709,1026,177,8.17994448216,-23.52185673021,19.76787080946,2,1,18
+2025-03-11T12:38:27.140655,479392709,1026,177,7.78459618728,-22.62557197602,19.064656623375,2,1,18
+2025-03-11T12:38:27.265655,479392709,1026,177,7.36100872848,-21.66460731711,18.31483946826,2,1,18
+2025-03-11T12:38:27.390655,479392709,1026,177,6.90918210576,-20.6204949297,17.509081775085,2,1,18
+2025-03-11T12:38:27.515655,479392709,1026,177,6.43382284644,-19.50709276854,16.670567317905,2,1,18
+2025-03-11T12:38:27.640655,479392709,1026,177,5.93493095052,-18.36133648119,15.78101029866,2,1,18
+2025-03-11T12:38:27.765655,479392709,1026,177,5.40779989068,-17.1693681129,14.844947645385,2,1,18
+2025-03-11T12:38:27.890655,479392709,1026,177,4.84301661228,-15.92193957795,13.88079078318,2,1,18
+2025-03-11T12:38:28.015655,479392709,1026,177,4.27352680656,-14.609866572855,12.870081890595,2,1,18
+2025-03-11T12:38:28.140655,479392709,1026,177,3.68050436424,-13.26543944157,11.83143102102,2,1,18
+2025-03-11T12:38:28.265655,479392709,1026,177,3.09218844924,-11.87484983775,10.73248548048,2,1,18
+2025-03-11T12:38:28.390655,479392709,1026,177,2.45680726104,-10.44725371722,9.63324339264,2,1,18
+2025-03-11T12:38:28.515655,479392709,1026,177,1.81671954552,-8.991948774105,8.50612441248,2,1,18
+2025-03-11T12:38:28.640655,479392709,1026,177,1.16251224804,-7.51353779052,7.36037273232,2,1,18
+2025-03-11T12:38:28.765655,479392709,1026,177,0.51301147788,-6.021283026015,6.191457653565,2,1,18
+2025-03-11T12:38:28.890655,479392709,1026,177,-0.16943498352,-4.47819213771,5.02220358945,2,1,18
+2025-03-11T12:38:29.015655,479392709,1026,177,-0.84246839028,-2.93049846729,3.825224864955,2,1,18
+2025-03-11T12:38:29.140655,479392709,1026,177,-1.52491485168,-1.37355671115,2.61893686347,2,1,18
+2025-03-11T12:38:29.265655,479392709,1026,177,-2.21677436772,0.178782262875,1.40803270326,2,1,18
+2025-03-11T12:38:29.390655,479392709,1026,177,-2.90392735644,1.74496501782,0.201685846545,2,1,18
+2025-03-11T12:38:29.515655,479392709,1026,177,-3.57225423588,3.28803464538,-1.027599175575,2,1,18
+2025-03-11T12:38:29.640655,479392709,1026,177,-4.26411375192,4.87269231102,-2.238673672035,2,1,18
+2025-03-11T12:38:29.765655,479392709,1026,177,-4.94656021332,6.42963406716,-3.41724097143,2,1,18
+2025-03-11T12:38:29.890655,479392709,1026,177,-5.61488709276,7.949618914995,-4.60020315465,2,1,18
+2025-03-11T12:38:30.015594,479392713,1022,178,-6.28792049952,9.45575998191,-5.77386229032,2,1,18
+2025-03-11T12:38:30.140594,479392713,1022,178,-6.942127797,10.95725574522,-6.961316692365,2,1,18
+2025-03-11T12:38:30.265594,479392713,1022,178,-7.59162856716,12.43565964189,-8.088577716735,2,1,18
+2025-03-11T12:38:30.390594,479392713,1022,178,-8.22230322804,13.854014763615,-9.178520715315,2,1,18
+2025-03-11T12:38:30.515594,479392713,1022,178,-8.82944525232,15.24001575915,-10.259002204965,2,1,18
+2025-03-11T12:38:30.640594,479392713,1022,178,-9.42246769464,16.59829375827,-11.311586426835,2,1,18
+2025-03-11T12:38:30.765594,479392713,1022,178,-10.01078360964,17.91501206697,-12.34084087215,2,1,18
+2025-03-11T12:38:30.890594,479392713,1022,178,-10.5661538334,19.176277295925,-13.32815094522,2,1,18
+2025-03-11T12:38:31.015594,479392713,1022,178,-11.09328489324,20.40979826772,-14.25981248523,2,1,18
+2025-03-11T12:38:31.140594,479392713,1022,178,-11.61100289844,21.56481681462,-15.167939390955,2,1,18
+2025-03-11T12:38:31.265594,479392713,1022,178,-12.10048173972,22.68285719247,-16.024989213135,2,1,18
+2025-03-11T12:38:31.390594,479392713,1022,178,-12.55230836244,23.731586535825,-16.835391357075,2,1,18
+2025-03-11T12:38:31.515594,479392713,1022,178,-12.9900154032,24.70180636737,-17.60376821094,2,1,18
+2025-03-11T12:38:31.640594,479392713,1022,178,-13.39948328004,25.63043107392,-18.33028388154,2,1,18
+2025-03-11T12:38:31.765594,479392713,1022,178,-13.78071199296,26.489758919805,-18.98245154727,2,1,18
+2025-03-11T12:38:31.890594,479392713,1022,178,-14.12428848732,27.25669095147,-19.583229748995,2,1,18
+2025-03-11T12:38:32.015594,479392713,1022,178,-14.43021276312,27.958928904585,-20.13738460623,2,1,18
+2025-03-11T12:38:32.140594,479392713,1022,178,-14.71260440232,28.60111099584,-20.63111066487,2,1,18
+2025-03-11T12:38:32.265594,479392713,1022,178,-14.95734382296,29.160131184765,-21.06887580999,2,1,18
+2025-03-11T12:38:32.390594,479392713,1022,178,-15.16913755236,29.64984742611,-21.446143113555,2,1,18
+2025-03-11T12:38:32.515594,479392713,1022,178,-15.34798559052,30.061025807985,-21.744383440005,2,1,18
+2025-03-11T12:38:32.640594,479392713,1022,178,-15.49388793744,30.37519850661,-21.986600039415,2,1,18
+2025-03-11T12:38:32.765594,479392713,1022,178,-15.59272501116,30.643130776635,-22.191510487905,2,1,18
+2025-03-11T12:38:32.890594,479392713,1022,178,-15.65861639364,30.80482345152,-22.31724795678,2,1,18
+2025-03-11T12:38:33.015594,479392713,1022,178,-15.6962686122,30.864900574125,-22.377707318565,2,1,18
+2025-03-11T12:38:33.140594,479392713,1022,178,-15.68685555756,30.86950335624,-22.37309115984,2,1,18
+2025-03-11T12:38:33.265594,479392713,1022,178,-15.66802944828,30.78636980157,-22.30793076321,2,1,18
+2025-03-11T12:38:33.390594,479392713,1022,178,-15.6021380658,30.60159234696,-22.16821127454,2,1,18
+2025-03-11T12:38:33.515594,479392713,1022,178,-15.49388793744,30.35673068283,-21.97264235337,2,1,18
+2025-03-11T12:38:33.640594,479392713,1022,178,-15.34798559052,30.01947320448,-21.716443734165,2,1,18
+2025-03-11T12:38:33.765594,479392713,1022,178,-15.16443102504,29.61752164758,-21.41362177047,2,1,18
+2025-03-11T12:38:33.890594,479392713,1022,178,-14.96205035028,29.13243653601,-21.036399176115,2,1,18
+2025-03-11T12:38:34.015548,479392717,1019,179,-14.71260440232,28.550324480445,-20.580021706455,2,1,18
+2025-03-11T12:38:34.140548,479392717,1019,179,-14.43021276312,27.912759345135,-20.086319981565,2,1,18
+2025-03-11T12:38:34.265548,479392717,1019,179,-14.10546237804,27.20125913247,-19.53207570591,2,1,18
+2025-03-11T12:38:34.390548,479392717,1019,179,-13.76188588368,26.41124232108,-18.931175835435,2,1,18
+2025-03-11T12:38:34.515548,479392717,1019,179,-13.38536369808,25.55192156211,-18.260537889375,2,1,18
+2025-03-11T12:38:34.640548,479392717,1019,179,-12.9900154032,24.614084204415,-17.52938399745,2,1,18
+2025-03-11T12:38:34.765548,479392717,1019,179,-12.55230836244,23.648481328815,-16.761031477335,2,1,18
+2025-03-11T12:38:34.890548,479392717,1019,179,-12.08165563044,22.58125581402,-15.94587113046,2,1,18
+2025-03-11T12:38:35.015548,479392717,1019,179,-11.60629637112,21.481704520695,-15.084329089455,2,1,18
+2025-03-11T12:38:35.140548,479392717,1019,179,-11.09799142056,20.31284927979,-14.18538979197,2,1,18
+2025-03-11T12:38:35.265548,479392717,1019,179,-10.56144730608,19.08393109011,-13.24449197622,2,1,18
+2025-03-11T12:38:35.390548,479392717,1019,179,-10.001370555,17.81342486235,-12.25712304792,2,1,18
+2025-03-11T12:38:35.515548,479392717,1019,179,-9.42246769464,16.4782529037,-11.24165199411,2,1,18
+2025-03-11T12:38:35.640548,479392717,1019,179,-8.82003219768,15.115343774805,-10.175162711985,2,1,18
+2025-03-11T12:38:35.765548,479392717,1019,179,-8.1893575368,13.701605609025,-9.10834463223,2,1,18
+2025-03-11T12:38:35.890548,479392717,1019,179,-7.5775089852,12.269427967125,-7.986028564215,2,1,18
+2025-03-11T12:38:36.015548,479392717,1019,179,-6.93271474236,10.81873289304,-6.849683496045,2,1,18
+2025-03-11T12:38:36.140548,479392717,1019,179,-6.2832139722,9.335712040425,-5.685437201805,2,1,18
+2025-03-11T12:38:36.265548,479392717,1019,179,-5.61018056544,7.806486193785,-4.49779604634,2,1,18
+2025-03-11T12:38:36.390548,479392717,1019,179,-4.93714715868,6.286494259035,-3.319443792405,2,1,18
+2025-03-11T12:38:36.515548,479392717,1019,179,-4.26411375192,4.748034500505,-2.10403326735,2,1,18
+2025-03-11T12:38:36.640548,479392717,1019,179,-3.58166729052,3.181858832475,-0.90231671538,2,1,18
+2025-03-11T12:38:36.765548,479392717,1019,179,-2.90392735644,1.620307207305,0.29936531511,2,1,18
+2025-03-11T12:38:36.890548,479392717,1019,179,-2.21677436772,0.040273584525,1.50116505606,2,1,18
+2025-03-11T12:38:37.015548,479392717,1019,179,-1.51079526972,-1.51670360619,2.71212411321,2,1,18
+2025-03-11T12:38:37.140548,479392717,1019,179,-0.83776186296,-3.05516336472,3.918294404235,2,1,18
+2025-03-11T12:38:37.265548,479392717,1019,179,-0.1647284562,-4.598240079195,5.09676832692,2,1,18
+2025-03-11T12:38:37.390548,479392717,1019,179,0.51301147788,-6.12747301275,6.284419670115,2,1,18
+2025-03-11T12:38:37.515548,479392717,1019,179,1.17663183,-7.642833817725,7.458107097825,2,1,18
+2025-03-11T12:38:37.640548,479392717,1019,179,1.82142607284,-9.135081495315,8.603911403775,2,1,18
+2025-03-11T12:38:37.765548,479392717,1019,179,2.46151378836,-10.567301658705,9.730908715185,2,1,18
+2025-03-11T12:38:37.890548,479392717,1019,179,3.09218844924,-12.00412460421,10.830189282795,2,1,18
+2025-03-11T12:38:38.015472,479392721,1014,180,3.70403700084,-13.394749642605,11.910705293925,2,1,18
+2025-03-11T12:38:38.140472,479392721,1014,180,4.2829398612,-14.7345385572,12.953921383575,2,1,18
+2025-03-11T12:38:38.265472,479392721,1014,180,4.86654924888,-16.042015867095,13.9646365056,2,1,18
+2025-03-11T12:38:38.390472,479392721,1014,180,5.42191947264,-17.298664140105,14.938061893875,2,1,18
+2025-03-11T12:38:38.515472,479392721,1014,180,5.94905053248,-18.490632508395,15.86488431312,2,1,18
+2025-03-11T12:38:38.640472,479392721,1014,180,6.4479424284,-19.62253792791,16.754368331115,2,1,18
+2025-03-11T12:38:38.765472,479392721,1014,180,6.93271474236,-20.712869483175,17.592781495005,2,1,18
+2025-03-11T12:38:38.890472,479392721,1014,180,7.3892478924,-21.74775504561,18.38926047438,2,1,18
+2025-03-11T12:38:39.015472,479392721,1014,180,7.80342229656,-22.72717335447,19.139154589035,2,1,18
+2025-03-11T12:38:39.140472,479392721,1014,180,8.18465100948,-23.614202936025,19.846909661445,2,1,18
+2025-03-11T12:38:39.265472,479392721,1014,180,8.56117319508,-24.45043891527,20.50356558771,2,1,18
+2025-03-11T12:38:39.390472,479392721,1014,180,8.90474968944,-25.208137035045,21.085814653875,2,1,18
+2025-03-11T12:38:39.515472,479392721,1014,180,9.21067396524,-25.90114107627,21.62144037555,2,1,18
+2025-03-11T12:38:39.640472,479392721,1014,180,9.4836525498,-26.52945812586,22.09659258942,2,1,18
+2025-03-11T12:38:39.765472,479392721,1014,180,9.71427238848,-27.074606186205,22.511153585025,2,1,18
+2025-03-11T12:38:39.890472,479392721,1014,180,9.92135959056,-27.51352882524,22.85118209349,2,1,18
+2025-03-11T12:38:40.015472,479392721,1014,180,10.07667499212,-27.901586992815,23.153869929555,2,1,18
+2025-03-11T12:38:40.140472,479392721,1014,180,10.2131642844,-28.192660737885,23.377464016695,2,1,18
+2025-03-11T12:38:40.265472,479392721,1014,180,10.3072948308,-28.4097994056,23.545135670085,2,1,18
+2025-03-11T12:38:40.390472,479392721,1014,180,10.38730579524,-28.539194649615,23.666113248885,2,1,18
+2025-03-11T12:38:40.515472,479392721,1014,180,10.40613190452,-28.59000951267,23.694142373145,2,1,18
+2025-03-11T12:38:40.640472,479392721,1014,180,10.37318621328,-28.580725992375,23.67092180646,2,1,18
+2025-03-11T12:38:40.765472,479392721,1014,180,10.32612094008,-28.479082092435,23.59636271442,2,1,18
+2025-03-11T12:38:40.890472,479392721,1014,180,10.2602295576,-28.285070725935,23.442734207205,2,1,18
+2025-03-11T12:38:41.015472,479392721,1014,180,10.13785984728,-27.998635197555,23.228435251035,2,1,18
+2025-03-11T12:38:41.140472,479392721,1014,180,9.98254444572,-27.624427897815,22.948921001295,2,1,18
+2025-03-11T12:38:41.265472,479392721,1014,180,9.78487029828,-27.199370300445,22.6274663376,2,1,18
+2025-03-11T12:38:41.390472,479392721,1014,180,9.56366351424,-26.714256841215,22.231722524265,2,1,18
+2025-03-11T12:38:41.515472,479392721,1014,180,9.30951103896,-26.1182868309,21.775261865625,2,1,18
+2025-03-11T12:38:41.640472,479392721,1014,180,9.00829329048,-25.44375770037,21.26746436877,2,1,18
+2025-03-11T12:38:41.765472,479392721,1014,180,8.6835429054,-24.70917270798,20.703858190335,2,1,18
+2025-03-11T12:38:41.890472,479392721,1014,180,8.33996641104,-23.90068807281,20.070520165755,2,1,18
+2025-03-11T12:38:42.015396,479392725,1009,181,7.96815075276,-23.032140488865,19.38598338888,2,1,18
+2025-03-11T12:38:42.140396,479392725,1009,181,7.53985676664,-22.07116874304,18.645396280065,2,1,18
+2025-03-11T12:38:42.265396,479392725,1009,181,7.11156278052,-21.073261349655,17.844552980055,2,1,18
+2025-03-11T12:38:42.390396,479392725,1009,181,6.65032310316,-19.98758218491,17.01083520558,2,1,18
+2025-03-11T12:38:42.515396,479392725,1009,181,6.14672467992,-18.869520546315,16.13527435215,2,1,18
+2025-03-11T12:38:42.640396,479392725,1009,181,5.63371320204,-17.66833952688,15.22229417964,2,1,18
+2025-03-11T12:38:42.765396,479392725,1009,181,5.10187561488,-16.430194512225,14.258257299045,2,1,18
+2025-03-11T12:38:42.890396,479392725,1009,181,4.53238580916,-15.159674110635,13.261627761255,2,1,18
+2025-03-11T12:38:43.015396,479392725,1009,181,3.94877642148,-13.83372897696,12.23233483617,2,1,18
+2025-03-11T12:38:43.140396,479392725,1009,181,3.3416343972,-12.46157884926,11.184267166875,2,1,18
+2025-03-11T12:38:43.265396,479392725,1009,181,2.706253209,-11.047833596565,10.075857846255,2,1,18
+2025-03-11T12:38:43.390396,479392725,1009,181,2.08028507544,-9.60640078203,8.976563132625,2,1,18
+2025-03-11T12:38:43.515396,479392725,1009,181,1.42607777796,-8.118755886555,7.821522550935,2,1,18
+2025-03-11T12:38:43.640396,479392725,1009,181,0.77187048048,-6.64034490297,6.657290402715,2,1,18
+2025-03-11T12:38:43.765396,479392725,1009,181,0.12707623764,-5.115778533765,5.46973470738,2,1,18
+2025-03-11T12:38:43.890396,479392725,1009,181,-0.53183758716,-3.57734003598,4.282075447605,2,1,18
+2025-03-11T12:38:44.015396,479392725,1009,181,-1.22840363052,-2.01576006315,3.080352666195,2,1,18
+2025-03-11T12:38:44.140396,479392725,1009,181,-1.92026314656,-0.463421089125,1.874068623,2,1,18
+2025-03-11T12:38:44.265396,479392725,1009,181,-2.60270960796,1.093520667015,0.667780621515,2,1,18
+2025-03-11T12:38:44.390396,479392725,1009,181,-3.28986259668,2.66893733385,-0.543235019715,2,1,18
+2025-03-11T12:38:44.515396,479392725,1009,181,-3.97230905808,4.24434691377,-1.75886059023,2,1,18
+2025-03-11T12:38:44.640396,479392725,1009,181,-4.65475551948,5.79205475802,-2.9604798072,2,1,18
+2025-03-11T12:38:44.765396,479392725,1009,181,-5.3419085082,7.330535777295,-4.14358007634,2,1,18
+2025-03-11T12:38:44.890396,479392725,1009,181,-5.99611580568,8.850499364385,-5.321891579355,2,1,18
+2025-03-11T12:38:45.015396,479392725,1009,181,-6.65502963048,10.33353439083,-6.476918015025,2,1,18
+2025-03-11T12:38:45.140396,479392725,1009,181,-7.29041081868,11.802683114865,-7.613340042735,2,1,18
+2025-03-11T12:38:45.265396,479392725,1009,181,-7.93520506152,13.25337818895,-8.740444876875,2,1,18
+2025-03-11T12:38:45.390396,479392725,1009,181,-8.57058624972,14.685591265425,-9.83509118145,2,1,18
+2025-03-11T12:38:45.515396,479392725,1009,181,-9.17302174668,16.0669682181,-10.89705768156,2,1,18
+2025-03-11T12:38:45.640396,479392725,1009,181,-9.75663113436,17.392913351775,-11.92173048963,2,1,18
+2025-03-11T12:38:45.765396,479392725,1009,181,-10.32141441276,18.686511446175,-12.9369519765,2,1,18
+2025-03-11T12:38:45.890396,479392725,1009,181,-10.85795852724,19.90157876802,-13.89625725906,2,1,18
+2025-03-11T12:38:46.015350,479392729,1006,182,-11.38038305976,21.07045526967,-14.82756793884,2,1,18
+2025-03-11T12:38:46.140350,479392729,1006,182,-11.87927495568,22.220828512965,-15.69404870676,2,1,18
+2025-03-11T12:38:46.265350,479392729,1006,182,-12.34522116036,23.30189780868,-16.53237245223,2,1,18
+2025-03-11T12:38:46.390350,479392729,1006,182,-12.78292820112,24.31367024373,-17.32406889492,2,1,18
+2025-03-11T12:38:46.515350,479392729,1006,182,-13.2018091326,25.251543036,-18.064513959525,2,1,18
+2025-03-11T12:38:46.640350,479392729,1006,182,-13.59715742748,26.124743010465,-18.744505891785,2,1,18
+2025-03-11T12:38:46.765350,479392729,1006,182,-13.95956003112,26.951723817075,-19.37336188527,2,1,18
+2025-03-11T12:38:46.890350,479392729,1006,182,-14.29842999816,27.67709615832,-19.95081031044,2,1,18
+2025-03-11T12:38:47.015350,479392729,1006,182,-14.590234692,28.346994159075,-20.449322864055,2,1,18
+2025-03-11T12:38:47.140350,479392729,1006,182,-14.85380022192,28.947595299165,-20.91044834892,2,1,18
+2025-03-11T12:38:47.265350,479392729,1006,182,-15.0844200606,29.45580771195,-21.31095432348,2,1,18
+2025-03-11T12:38:47.390350,479392729,1006,182,-15.26797462608,29.9039288283,-21.660220794825,2,1,18
+2025-03-11T12:38:47.515350,479392729,1006,182,-15.42799655496,30.250441479285,-21.930358995765,2,1,18
+2025-03-11T12:38:47.640350,479392729,1006,182,-15.55036626528,30.54149396361,-22.135442051655,2,1,18
+2025-03-11T12:38:47.765350,479392729,1006,182,-15.6256707024,30.72628559205,-22.2798020328,2,1,18
+2025-03-11T12:38:47.890350,479392729,1006,182,-15.67744250292,30.827936578905,-22.377471897645,2,1,18
+2025-03-11T12:38:48.015350,479392729,1006,182,-15.71038819416,30.86492183487,-22.405458583845,2,1,18
+2025-03-11T12:38:48.140350,479392729,1006,182,-15.6962686122,30.81411405873,-22.358959179255,2,1,18
+2025-03-11T12:38:48.265350,479392729,1006,182,-15.62096417508,30.67549198974,-22.228702886655,2,1,18
+2025-03-11T12:38:48.390350,479392729,1006,182,-15.5080075194,30.45370801842,-22.060966148595,2,1,18
+2025-03-11T12:38:48.515350,479392729,1006,182,-15.3903443364,30.158045665065,-21.846628712655,2,1,18
+2025-03-11T12:38:48.640350,479392729,1006,182,-15.20678977092,29.769944976,-21.557740101255,2,1,18
+2025-03-11T12:38:48.765350,479392729,1006,182,-15.0138221508,29.29410795015,-21.203687134935,2,1,18
+2025-03-11T12:38:48.890350,479392729,1006,182,-14.79261536676,28.76282493147,-20.77997928201,2,1,18
+2025-03-11T12:38:49.015350,479392729,1006,182,-14.53375636416,28.17608174613,-20.29583640105,2,1,18
+2025-03-11T12:38:49.140350,479392729,1006,182,-14.237245143,27.492325790625,-19.788000424425,2,1,18
+2025-03-11T12:38:49.265350,479392729,1006,182,-13.89837517596,26.73925171371,-19.182685294665,2,1,18
+2025-03-11T12:38:49.390350,479392729,1006,182,-13.54067909964,25.893810170235,-18.53526168585,2,1,18
+2025-03-11T12:38:49.515350,479392729,1006,182,-13.15945038672,25.011397544625,-17.850631532265,2,1,18
+2025-03-11T12:38:49.640350,479392729,1006,182,-12.72174334596,24.05041162497,-17.096163696945,2,1,18
+2025-03-11T12:38:49.765350,479392729,1006,182,-12.27462325056,23.00168936853,-16.285771740735,2,1,18
+2025-03-11T12:38:49.890350,479392729,1006,182,-11.7898509366,21.90674085732,-15.447334243095,2,1,18
+2025-03-11T12:38:50.015274,479392733,1001,183,-11.28154598604,20.76097039614,-14.571617199435,2,1,18
+2025-03-11T12:38:50.140274,479392733,1001,183,-10.7544149262,19.56900202785,-13.65403501422,2,1,18
+2025-03-11T12:38:50.265274,479392733,1001,183,-10.21787081172,18.316999058445,-12.680674710615,2,1,18
+2025-03-11T12:38:50.390274,479392733,1001,183,-9.648381006,17.02339387713,-11.674683270045,2,1,18
+2025-03-11T12:38:50.515274,479392733,1001,183,-9.05535856368,15.69281761368,-10.622245050675,2,1,18
+2025-03-11T12:38:50.640274,479392733,1001,183,-8.4482165394,14.297582706255,-9.550955127555,2,1,18
+2025-03-11T12:38:50.765274,479392733,1001,183,-7.82224840584,12.870000759555,-8.44711329816,2,1,18
+2025-03-11T12:38:50.890274,479392733,1001,183,-7.18686721764,11.41008594741,-7.315360054965,2,1,18
+2025-03-11T12:38:51.015274,479392733,1001,183,-6.53736644748,9.945532918575,-6.151211095725,2,1,18
+2025-03-11T12:38:51.140274,479392733,1001,183,-5.87845262268,8.42556224457,-4.97288940498,2,1,18
+2025-03-11T12:38:51.265274,479392733,1001,183,-5.19600616128,6.90555613599,-3.7991368926,2,1,18
+2025-03-11T12:38:51.390274,479392733,1001,183,-4.52297275452,5.37633028935,-2.602255503105,2,1,18
+2025-03-11T12:38:51.515274,479392733,1001,183,-3.84993934776,3.814785751095,-1.400583660345,2,1,18
+2025-03-11T12:38:51.640274,479392733,1001,183,-3.16278635904,2.253219952095,-0.21274160544,2,1,18
+2025-03-11T12:38:51.765274,479392733,1001,183,-2.47563337032,0.691654153095,0.99820103454,2,1,18
+2025-03-11T12:38:51.890274,479392733,1001,183,-1.7884803816,-0.879145557795,2.213812459035,2,1,18
+2025-03-11T12:38:52.015274,479392733,1001,183,-1.09191433824,-2.431491618735,3.415486572945,2,1,18
+2025-03-11T12:38:52.140274,479392733,1001,183,-0.40946787684,-3.97458250704,4.626321690195,2,1,18
+2025-03-11T12:38:52.265274,479392733,1001,183,0.25415247528,-5.50379417985,5.809322353185,2,1,18
+2025-03-11T12:38:52.390274,479392733,1001,183,0.92247935472,-7.03762989552,6.983117303625,2,1,18
+2025-03-11T12:38:52.515274,479392733,1001,183,1.56727359756,-8.534494529055,8.147426411385,2,1,18
+2025-03-11T12:38:52.640274,479392733,1001,183,2.21677436772,-9.994430601945,9.26996998374,2,1,18
+2025-03-11T12:38:52.765274,479392733,1001,183,2.84274250128,-11.449714284315,10.39705840071,2,1,18
+2025-03-11T12:38:52.890274,479392733,1001,183,3.44988452556,-12.849566147685,11.48685312564,2,1,18
+2025-03-11T12:38:53.015274,479392733,1001,183,4.06173307716,-14.198638582575,12.5301891969,2,1,18
+2025-03-11T12:38:53.140274,479392733,1001,183,4.6359294102,-15.51533563053,13.54555272798,2,1,18
+2025-03-11T12:38:53.265274,479392733,1001,183,5.2007126886,-16.77199807737,14.537478959775,2,1,18
+2025-03-11T12:38:53.390274,479392733,1001,183,5.73725680308,-17.996299311105,15.48297255879,2,1,18
+2025-03-11T12:38:53.515274,479392733,1001,183,6.25026828096,-19.183629462705,16.391259613035,2,1,18
+2025-03-11T12:38:53.640274,479392733,1001,183,6.74916017688,-20.30630097033,17.248354144425,2,1,18
+2025-03-11T12:38:53.765274,479392733,1001,183,7.21981290888,-21.35967561729,18.06344149005,2,1,18
+2025-03-11T12:38:53.890274,479392733,1001,183,7.65751994964,-22.35298022856,18.841180246695,2,1,18
+2025-03-11T12:38:54.015213,479392737,997,184,8.0716943538,-23.28622897797,19.5446298537,2,1,18
+2025-03-11T12:38:54.140213,479392737,997,184,8.43880348476,-24.150152519055,20.21527175805,2,1,18
+2025-03-11T12:38:54.265213,479392737,997,184,8.78708650644,-24.935559461415,20.84849830161,2,1,18
+2025-03-11T12:38:54.390213,479392737,997,184,9.10242383688,-25.660896368085,21.402795203055,2,1,18
+2025-03-11T12:38:54.515213,479392737,997,184,9.38481547608,-26.30307845934,21.905761495725,2,1,18
+2025-03-11T12:38:54.640213,479392737,997,184,9.63426142404,-26.866722691125,22.34818127934,2,1,18
+2025-03-11T12:38:54.765213,479392737,997,184,9.85076168076,-27.33336123966,22.71147675084,2,1,18
+2025-03-11T12:38:54.890213,479392737,997,184,10.03431624624,-27.75378062034,23.03749663461,2,1,18
+2025-03-11T12:38:55.015213,479392737,997,184,10.20845775708,-28.104931488015,23.293829381445,2,1,18
+2025-03-11T12:38:55.140213,479392737,997,184,10.30258830348,-28.345154935455,23.48472328866,2,1,18
+2025-03-11T12:38:55.265213,479392737,997,184,10.37318621328,-28.5114716532,23.63359586409,2,1,18
+2025-03-11T12:38:55.390213,479392737,997,184,10.41083843184,-28.599250511475,23.694201228375,2,1,18
+2025-03-11T12:38:55.515213,479392737,997,184,10.4249580138,-28.603888728165,23.6896360083,2,1,18
+2025-03-11T12:38:55.640213,479392737,997,184,10.4014253772,-28.534598954415,23.63377865922,2,1,18
+2025-03-11T12:38:55.765213,479392737,997,184,10.33553399472,-28.38214019142,23.517330091875,2,1,18
+2025-03-11T12:38:55.890213,479392737,997,184,10.23199039368,-28.15113648204,23.33570471073,2,1,18
+2025-03-11T12:38:56.015213,479392737,997,184,10.0955011014,-27.82312708941,23.0841952515,2,1,18
+2025-03-11T12:38:56.140213,479392737,997,184,9.92135959056,-27.41195579445,22.76748464472,2,1,18
+2025-03-11T12:38:56.265213,479392737,997,184,9.70015280652,-26.940693203055,22.408774768755,2,1,18
+2025-03-11T12:38:56.390213,479392737,997,184,9.44129380392,-26.37703479744,21.980194960725,2,1,18
+2025-03-11T12:38:56.515213,479392737,997,184,9.17302174668,-25.73487396693,21.486499465275,2,1,18
+2025-03-11T12:38:56.640213,479392737,997,184,8.86709747088,-25.04648688165,20.918557258245,2,1,18
+2025-03-11T12:38:56.765213,479392737,997,184,8.53293403116,-24.251867288145,20.31765342948,2,1,18
+2025-03-11T12:38:56.890213,479392737,997,184,8.15641184556,-23.39716348512,19.651659934185,2,1,18
+2025-03-11T12:38:57.015213,479392737,997,184,7.75165049604,-22.477779777375,18.94830370389,2,1,18
+2025-03-11T12:38:57.140213,479392737,997,184,7.3186499826,-21.498333120855,18.1937487213,2,1,18
+2025-03-11T12:38:57.265213,479392737,997,184,6.87623641452,-20.45885186322,17.369555269275,2,1,18
+2025-03-11T12:38:57.390213,479392737,997,184,6.38675757324,-19.336194529425,16.503240879315,2,1,18
+2025-03-11T12:38:57.515213,479392737,997,184,5.86433304072,-18.18116889561,15.618204370935,2,1,18
+2025-03-11T12:38:57.640213,479392737,997,184,5.32778892624,-16.96148461782,14.668114988655,2,1,18
+2025-03-11T12:38:57.765213,479392737,997,184,4.77241870248,-15.67713460914,13.68530336385,2,1,18
+2025-03-11T12:38:57.890213,479392737,997,184,4.19822236944,-14.36505451713,12.665344049505,2,1,18
+2025-03-11T12:38:58.015136,479392741,992,185,3.6004933998,-13.016003342985,11.612798307405,2,1,18
+2025-03-11T12:38:58.140136,479392741,992,185,2.99335137552,-11.625385391505,10.52767236699,2,1,18
+2025-03-11T12:38:58.265136,479392741,992,185,2.35797018732,-10.17470449125,9.4283086104,2,1,18
+2025-03-11T12:38:58.390136,479392741,992,185,1.7178824718,-8.737867371915,8.28280649718,2,1,18
+2025-03-11T12:38:58.515136,479392741,992,185,1.06838170164,-7.23637869552,7.141563453015,2,1,18
+2025-03-11T12:38:58.640136,479392741,992,185,0.4000548222,-5.73024471552,5.96329438806,2,1,18
+2025-03-11T12:38:58.765136,479392741,992,185,-0.2823916392,-4.187153827215,4.775559855885,2,1,18
+2025-03-11T12:38:58.890136,479392741,992,185,-0.95542504596,-2.64407711274,3.592465816185,2,1,18
+2025-03-11T12:38:59.015136,479392741,992,185,-1.62845845272,-1.082532574485,2.37693362238,2,1,18
+2025-03-11T12:38:59.140136,479392741,992,185,-2.32031796876,0.474423355485,1.152144777375,2,1,18
+2025-03-11T12:38:59.265136,479392741,992,185,-3.00276443016,2.040599023515,-0.06343212564,2,1,18
+2025-03-11T12:38:59.390136,479392741,992,185,-3.6946239462,3.597554953485,-1.25588015154,2,1,18
+2025-03-11T12:38:59.515136,479392741,992,185,-4.38177693492,5.168354664375,-2.46687145902,2,1,18
+2025-03-11T12:38:59.640136,479392741,992,185,-5.05010381436,6.71604124788,-3.67770034683,2,1,18
+2025-03-11T12:38:59.765136,479392741,992,185,-5.7184306938,8.236026095715,-4.87914299811,2,1,18
+2025-03-11T12:38:59.890136,479392741,992,185,-6.38675757324,9.751393987605,-6.05284061355,2,1,18
+2025-03-11T12:39:00.015136,479392741,992,185,-7.05037792536,11.22981914502,-7.19861266917,2,1,18
+2025-03-11T12:39:00.140136,479392741,992,185,-7.68105258624,12.685109914305,-8.321091156855,2,1,18
+2025-03-11T12:39:00.265136,479392741,992,185,-8.3070207198,14.112691861005,-9.411072635205,2,1,18
+2025-03-11T12:39:00.390136,479392741,992,185,-8.94710843532,15.507976376835,-10.47781375542,2,1,18
+2025-03-11T12:39:00.515136,479392741,992,185,-9.53542435032,16.833928597425,-11.53945768734,2,1,18
+2025-03-11T12:39:00.640136,479392741,992,185,-10.10020762872,18.15061147155,-12.5363203749,2,1,18
+2025-03-11T12:39:00.765136,479392741,992,185,-10.6602843798,19.407266831475,-13.51437606792,2,1,18
+2025-03-11T12:39:00.890136,479392741,992,185,-11.178002385,20.617688849715,-14.45513579775,2,1,18
+2025-03-11T12:39:01.015136,479392741,992,185,-11.68630733556,21.763459310895,-15.353953426485,2,1,18
+2025-03-11T12:39:01.140136,479392741,992,185,-12.17578617684,22.8768827328,-16.192498446855,2,1,18
+2025-03-11T12:39:01.265136,479392741,992,185,-12.62761279956,23.907144252375,-16.993563021765,2,1,18
+2025-03-11T12:39:01.390136,479392741,992,185,-13.05590678568,24.863499042255,-17.76184649892,2,1,18
+2025-03-11T12:39:01.515136,479392741,992,185,-13.46537466252,25.755188101245,-18.465066914445,2,1,18
+2025-03-11T12:39:01.640136,479392741,992,185,-13.84189684812,26.61912581616,-19.108008492165,2,1,18
+2025-03-11T12:39:01.765136,479392741,992,185,-14.17135376052,27.38603658708,-19.7087561307,2,1,18
+2025-03-11T12:39:01.890136,479392741,992,185,-14.472571509,28.07903354139,-20.24899178166,2,1,18
+2025-03-11T12:39:02.015075,479392745,988,186,-14.75025662088,28.725825501675,-20.747352103335,2,1,18
+2025-03-11T12:39:02.140075,479392745,988,186,-14.9902895142,29.257136868015,-21.17110070718,2,1,18
+2025-03-11T12:39:02.265075,479392745,988,186,-15.19267018896,29.71913719986,-21.538961398755,2,1,18
+2025-03-11T12:39:02.390075,479392745,988,186,-15.3668116998,30.107223715095,-21.82320951768,2,1,18
+2025-03-11T12:39:02.515075,479392745,988,186,-15.49859446476,30.430609064865,-22.07468445543,2,1,18
+2025-03-11T12:39:02.640075,479392745,988,186,-15.58801848384,30.65235760161,-22.246990371855,2,1,18
+2025-03-11T12:39:02.765075,479392745,988,186,-15.66802944828,30.81407153724,-22.331177350785,2,1,18
+2025-03-11T12:39:02.890075,479392745,988,186,-15.6962686122,30.86951753007,-22.39159200336,2,1,18
+2025-03-11T12:39:03.015075,479392745,988,186,-15.67744250292,30.837170490795,-22.37290044813,2,1,18
+2025-03-11T12:39:03.140075,479392745,988,186,-15.63979028436,30.726306852795,-22.284452713005,2,1,18
+2025-03-11T12:39:03.265075,479392745,988,186,-15.56448584724,30.52766435652,-22.14001973061,2,1,18
+2025-03-11T12:39:03.390075,479392745,988,186,-15.46564877352,30.26434904244,-21.948993966915,2,1,18
+2025-03-11T12:39:03.515075,479392745,988,186,-15.31503989928,29.936318389065,-21.68359359345,2,1,18
+2025-03-11T12:39:03.640075,479392745,988,186,-15.12677880648,29.511274965525,-21.36677942223,2,1,18
+2025-03-11T12:39:03.765075,479392745,988,186,-14.91498507708,29.0030909004,-20.980174549635,2,1,18
+2025-03-11T12:39:03.890075,479392745,988,186,-14.66553912912,28.411744932945,-20.523748412475,2,1,18
+2025-03-11T12:39:04.015075,479392745,988,186,-14.36432138064,27.77876840592,-20.00692968534,2,1,18
+2025-03-11T12:39:04.140075,479392745,988,186,-14.05369057752,27.04882163022,-19.443378403845,2,1,18
+2025-03-11T12:39:04.265075,479392745,988,186,-13.71011408316,26.24033699505,-18.81466049628,2,1,18
+2025-03-11T12:39:04.390075,479392745,988,186,-13.33829842488,25.37640636705,-18.157868755245,2,1,18
+2025-03-11T12:39:04.515075,479392745,988,186,-12.92412402072,24.438540661695,-17.422053995385,2,1,18
+2025-03-11T12:39:04.640075,479392745,988,186,-12.46759087068,23.43135683493,-16.6534417206,2,1,18
+2025-03-11T12:39:04.765075,479392745,988,186,-12.001644666,22.38260623083,-15.83376877944,2,1,18
+2025-03-11T12:39:04.890075,479392745,988,186,-11.51216582472,21.2460980292,-14.94890092017,2,1,18
+2025-03-11T12:39:05.015075,479392745,988,186,-10.99444781952,20.077228614465,-14.031460779165,2,1,18
+2025-03-11T12:39:05.140075,479392745,988,186,-10.4484906504,18.848296250955,-13.081302353925,2,1,18
+2025-03-11T12:39:05.265075,479392745,988,186,-9.88841389932,17.56393915536,-12.084620190345,2,1,18
+2025-03-11T12:39:05.390075,479392745,988,186,-9.295391457,16.21489506813,-11.050565104035,2,1,18
+2025-03-11T12:39:05.515075,479392745,988,186,-8.70236901468,14.85661706901,-9.98412053112,2,1,18
+2025-03-11T12:39:05.640075,479392745,988,186,-8.07640088112,13.452119902035,-8.898880838535,2,1,18
+2025-03-11T12:39:05.765075,479392745,988,186,-7.44572622024,11.99682913275,-7.77640235085,2,1,18
+2025-03-11T12:39:05.890075,479392745,988,186,-6.81975808668,10.55077936227,-6.635502250335,2,1,18
+2025-03-11T12:39:06.015014,479392749,984,187,-6.15613773456,9.04926942513,-5.48498840895,2,1,18
+2025-03-11T12:39:06.140014,479392749,984,187,-5.47839780048,7.52465344752,-4.31122175055,2,1,18
+2025-03-11T12:39:06.265014,479392749,984,187,-4.80536439372,5.99542760088,-3.1282007121,2,1,18
+2025-03-11T12:39:06.390014,479392749,984,187,-4.12762445964,4.4431098876,-1.93580758314,2,1,18
+2025-03-11T12:39:06.515014,479392749,984,187,-3.44047147092,2.87231017671,-0.720196158645,2,1,18
+2025-03-11T12:39:06.640014,479392749,984,187,-2.7533184822,1.3199782896,0.490697813835,2,1,18
+2025-03-11T12:39:06.765014,479392749,984,187,-2.05675243884,-0.236984727285,1.7247370806,2,1,18
+2025-03-11T12:39:06.890014,479392749,984,187,-1.37901250476,-1.8031533084,2.921823327825,2,1,18
+2025-03-11T12:39:07.015014,479392749,984,187,-0.69185951604,-3.369336063345,4.11892995051,2,1,18
+2025-03-11T12:39:07.140014,479392749,984,187,-0.01411958196,-4.91703682068,5.325159096765,2,1,18
+2025-03-11T12:39:07.265014,479392749,984,187,0.64479424284,-6.42315662685,6.517268137305,2,1,18
+2025-03-11T12:39:07.390014,479392749,984,187,1.30370806764,-7.93851034491,7.672464909225,2,1,18
+2025-03-11T12:39:07.515014,479392749,984,187,1.9532088378,-9.40768032969,8.82277785117,2,1,18
+2025-03-11T12:39:07.640014,479392749,984,187,2.59800308064,-10.86299235972,9.94990701906,2,1,18
+2025-03-11T12:39:07.765014,479392749,984,187,3.21926468688,-12.25824852789,11.035087856415,2,1,18
+2025-03-11T12:39:07.890014,479392749,984,187,3.82640671116,-13.63039865559,12.106256110785,2,1,18
+2025-03-11T12:39:08.015014,479392749,984,187,4.39589651688,-14.979407308245,13.140260258445,2,1,18
+2025-03-11T12:39:08.140014,479392749,984,187,4.9653863226,-16.286863357395,14.14170458325,2,1,18
+2025-03-11T12:39:08.265014,479392749,984,187,5.51605001904,-17.52503671971,15.087301746705,2,1,18
+2025-03-11T12:39:08.390014,479392749,984,187,6.03376802424,-18.69852309039,16.01400645549,2,1,18
+2025-03-11T12:39:08.515014,479392749,984,187,6.54677950212,-19.82121585876,16.903472369175,2,1,18
+2025-03-11T12:39:08.640014,479392749,984,187,7.0127257068,-20.89766819853,17.73715166388,2,1,18
+2025-03-11T12:39:08.765014,479392749,984,187,7.46455232952,-21.92331276216,18.524331553995,2,1,18
+2025-03-11T12:39:08.890014,479392749,984,187,7.883433261,-22.893504246045,19.260326837835,2,1,18
+2025-03-11T12:39:09.015014,479392749,984,187,8.26936850124,-23.780540914515,19.9449915129,2,1,18
+2025-03-11T12:39:09.140014,479392749,984,187,8.6364776322,-24.612145763985,20.583122261895,2,1,18
+2025-03-11T12:39:09.265014,479392749,984,187,8.96122801728,-25.35134771232,21.16523324214,2,1,18
+2025-03-11T12:39:09.390014,479392749,984,187,9.26244576576,-26.03511075474,21.691559874555,2,1,18
+2025-03-11T12:39:09.515014,479392749,984,187,9.530717823,-26.64033593769,22.16196011493,2,1,18
+2025-03-11T12:39:09.640014,479392749,984,187,9.78016377096,-27.157810610025,22.567175624925,2,1,18
+2025-03-11T12:39:09.765014,479392749,984,187,9.98254444572,-27.605960074035,22.911862730175,2,1,18
+2025-03-11T12:39:09.890014,479392749,984,187,10.12844679264,-27.96630233211,23.182043369175,2,1,18
+2025-03-11T12:39:10.014953,479392753,980,188,10.25081650296,-28.25273786049,23.405582559375,2,1,18
+2025-03-11T12:39:10.139953,479392753,980,188,10.34024052204,-28.446784661565,23.56850223927,2,1,18
+2025-03-11T12:39:10.264953,479392753,980,188,10.39671884988,-28.57152751506,23.65244360955,2,1,18
+2025-03-11T12:39:10.389953,479392753,980,188,10.41083843184,-28.617718335255,23.694298563375,2,1,18
+2025-03-11T12:39:10.514953,479392753,980,188,10.42025148648,-28.58541381747,23.66180778348,2,1,18
+2025-03-11T12:39:10.639953,479392753,980,188,10.35906663132,-28.456046921115,23.573211774705,2,1,18
+2025-03-11T12:39:10.764953,479392753,980,188,10.25081650296,-28.23427003671,23.414725458405,2,1,18
+2025-03-11T12:39:10.889953,479392753,980,188,10.14727290192,-27.943245900045,23.191202685375,2,1,18
+2025-03-11T12:39:11.014953,479392753,980,188,9.98725097304,-27.56903151339,22.902438013875,2,1,18
+2025-03-11T12:39:11.139953,479392753,980,188,9.77545724364,-27.143952655275,22.557852201915,2,1,18
+2025-03-11T12:39:11.264953,479392753,980,188,9.54013087764,-26.617265331795,22.15261858761,2,1,18
+2025-03-11T12:39:11.389953,479392753,980,188,9.28127187504,-26.012054322675,21.68685883971,2,1,18
+2025-03-11T12:39:11.514953,479392753,980,188,8.98476065388,-25.32829836717,21.142061926965,2,1,18
+2025-03-11T12:39:11.639953,479392753,980,188,8.66942332344,-24.579876680775,20.55992265468,2,1,18
+2025-03-11T12:39:11.764953,479392753,980,188,8.30231419248,-23.75288878725,19.912576005405,2,1,18
+2025-03-11T12:39:11.889953,479392753,980,188,7.92108547956,-22.87047616164,19.20946538376,2,1,18
+2025-03-11T12:39:12.014953,479392753,980,188,7.5069110754,-21.914142632505,18.478173405915,2,1,18
+2025-03-11T12:39:12.139953,479392753,980,188,7.05037792536,-20.874640114125,17.686290209805,2,1,18
+2025-03-11T12:39:12.264953,479392753,980,188,6.57031213872,-19.793549557665,16.838695667115,2,1,18
+2025-03-11T12:39:12.389953,479392753,980,188,6.07612677012,-18.661651225065,15.97694253894,2,1,18
+2025-03-11T12:39:12.514953,479392753,980,188,5.5537022376,-17.46968994369,15.031649839365,2,1,18
+2025-03-11T12:39:12.639953,479392753,980,188,4.99833201384,-16.21304167068,14.062844568105,2,1,18
+2025-03-11T12:39:12.764953,479392753,980,188,4.41942915348,-14.910188403645,13.056784084575,2,1,18
+2025-03-11T12:39:12.889953,479392753,980,188,3.84523282044,-13.56578962002,12.022794082935,2,1,18
+2025-03-11T12:39:13.014953,479392753,980,188,3.23809079616,-12.179788624485,10.96541317836,2,1,18
+2025-03-11T12:39:13.139953,479392753,980,188,2.62153571724,-10.761454763505,9.852400157895,2,1,18
+2025-03-11T12:39:13.264953,479392753,980,188,1.98615452904,-9.32924168703,8.75775385332,2,1,18
+2025-03-11T12:39:13.389953,479392753,980,188,1.34606681352,-7.86008587608,7.607461286835,2,1,18
+2025-03-11T12:39:13.514953,479392753,980,188,0.69656604336,-6.349363287795,6.433828756065,2,1,18
+2025-03-11T12:39:13.639953,479392753,980,188,0.0235326366,-4.810903529265,5.250759050115,2,1,18
+2025-03-11T12:39:13.764953,479392753,980,188,-0.65420729748,-3.28167059571,4.049247355875,2,1,18
+2025-03-11T12:39:13.889953,479392753,980,188,-1.35077334084,-1.715473666935,2.83363988967,2,1,18
+2025-03-11T12:39:14.014877,479392757,975,189,-2.03321980224,-0.167765822685,1.6320206727,2,1,18
+2025-03-11T12:39:14.139877,479392757,975,189,-2.71566626364,1.398409845345,0.425684003715,2,1,18
+2025-03-11T12:39:14.264877,479392757,975,189,-3.40281925236,2.969209556235,-0.785307303765,2,1,18
+2025-03-11T12:39:14.389877,479392757,975,189,-4.08997224108,4.521541443345,-1.99158115923,2,1,18
+2025-03-11T12:39:14.514877,479392757,975,189,-4.76771217516,6.06924220068,-3.188570071455,2,1,18
+2025-03-11T12:39:14.639877,479392757,975,189,-5.4360390546,7.61231182824,-4.371653923425,2,1,18
+2025-03-11T12:39:14.764877,479392757,975,189,-6.10907246136,9.1230698511,-5.554577626875,2,1,18
+2025-03-11T12:39:14.889877,479392757,975,189,-6.77269281348,10.62457978824,-6.718951819305,2,1,18
+2025-03-11T12:39:15.014877,479392757,975,189,-7.40807400168,12.066026776605,-7.845987610485,2,1,18
+2025-03-11T12:39:15.139877,479392757,975,189,-8.02933560792,13.52130337206,-8.954585371665,2,1,18
+2025-03-11T12:39:15.264877,479392757,975,189,-8.65059721416,14.92579345212,-10.053675227565,2,1,18
+2025-03-11T12:39:15.389877,479392757,975,189,-9.2718588204,16.288730928675,-11.124825377625,2,1,18
+2025-03-11T12:39:15.514877,479392757,975,189,-9.8601747354,17.623917061155,-12.131076572865,2,1,18
+2025-03-11T12:39:15.639877,479392757,975,189,-10.41083843184,18.90825998292,-13.132358478,2,1,18
+2025-03-11T12:39:15.764877,479392757,975,189,-10.95679560096,20.13719234643,-14.087137020255,2,1,18
+2025-03-11T12:39:15.889877,479392757,975,189,-11.47451360616,21.315295673055,-15.009245945775,2,1,18
+2025-03-11T12:39:16.014877,479392757,975,189,-11.97340550208,22.433350224735,-15.87093626043,2,1,18
+2025-03-11T12:39:16.139877,479392757,975,189,-12.44405823408,23.50057573953,-16.69071672432,2,1,18
+2025-03-11T12:39:16.264877,479392757,975,189,-12.89117832948,24.50312843652,-17.46390440691,2,1,18
+2025-03-11T12:39:16.389877,479392757,975,189,-13.29123315168,25.41327114546,-18.185682250035,2,1,18
+2025-03-11T12:39:16.514877,479392757,975,189,-13.66775533728,26.28182581632,-18.87022921464,2,1,18
+2025-03-11T12:39:16.639877,479392757,975,189,-14.0254514136,27.099565624125,-19.49440623588,2,1,18
+2025-03-11T12:39:16.764877,479392757,975,189,-14.354908326,27.829540747485,-20.048758034265,2,1,18
+2025-03-11T12:39:16.889877,479392757,975,189,-14.64671301984,28.48097092446,-20.53793301885,2,1,18
+2025-03-11T12:39:17.014877,479392757,975,189,-14.90086549512,29.05385615505,-20.99427200874,2,1,18
+2025-03-11T12:39:17.139877,479392757,975,189,-15.1079526972,29.548182265425,-21.371553458325,2,1,18
+2025-03-11T12:39:17.264877,479392757,975,189,-15.28680073536,29.973211515135,-21.697587488115,2,1,18
+2025-03-11T12:39:17.389877,479392757,975,189,-15.44211613692,30.30586621137,-21.958402266045,2,1,18
+2025-03-11T12:39:17.514877,479392757,975,189,-15.54565973796,30.559954700475,-22.163249901015,2,1,18
+2025-03-11T12:39:17.639877,479392757,975,189,-15.63037722972,30.744760502745,-22.312250374635,2,1,18
+2025-03-11T12:39:17.764877,479392757,975,189,-15.68214903024,30.8464114896,-22.386819654405,2,1,18
+2025-03-11T12:39:17.889877,479392757,975,189,-15.68685555756,30.85103553246,-22.396094409915,2,1,18
+2025-03-11T12:39:18.014816,479392761,971,190,-15.66332292096,30.795596626545,-22.3449301791,2,1,18
+2025-03-11T12:39:18.139816,479392761,971,190,-15.60684459312,30.638535081435,-22.219237419435,2,1,18
+2025-03-11T12:39:18.264816,479392761,971,190,-15.50330099208,30.39368050422,-22.04677927107,2,1,18
+2025-03-11T12:39:18.389816,479392761,971,190,-15.3668116998,30.11184067104,-21.800133266355,2,1,18
+2025-03-11T12:39:18.514816,479392761,971,190,-15.19737671628,29.719144286775,-21.483530182305,2,1,18
+2025-03-11T12:39:18.639816,479392761,971,190,-14.98558298688,29.24789586921,-21.13408091583,2,1,18
+2025-03-11T12:39:18.764816,479392761,971,190,-14.76437620284,28.68891111486,-20.68712647533,2,1,18
+2025-03-11T12:39:18.889816,479392761,971,190,-14.49139761828,28.05136015338,-20.20268535993,2,1,18
+2025-03-11T12:39:19.014816,479392761,971,190,-14.15723417856,27.34446272283,-19.666925510625,2,1,18
+2025-03-11T12:39:19.139816,479392761,971,190,-13.82777726616,26.591402819745,-19.06625087334,2,1,18
+2025-03-11T12:39:19.264816,479392761,971,190,-13.47008118984,25.74596127627,-18.409587030495,2,1,18
+2025-03-11T12:39:19.389816,479392761,971,190,-13.05120025836,24.831173263725,-17.701604453745,2,1,18
+2025-03-11T12:39:19.514816,479392761,971,190,-12.62761279956,23.85635773698,-16.947094180365,2,1,18
+2025-03-11T12:39:19.639816,479392761,971,190,-12.17107964952,22.8168552186,-16.136730516195,2,1,18
+2025-03-11T12:39:19.764816,479392761,971,190,-11.6957203902,21.717303925275,-15.279808592205,2,1,18
+2025-03-11T12:39:19.889816,479392761,971,190,-11.18270891232,20.56229246529,-14.376311991225,2,1,18
+2025-03-11T12:39:20.014816,479392761,971,190,-10.65087132516,19.34723223036,-13.45859794953,2,1,18
+2025-03-11T12:39:20.139816,479392761,971,190,-10.10491415604,18.095215087125,-12.49907762151,2,1,18
+2025-03-11T12:39:20.264816,479392761,971,190,-9.530717823,16.76928412728,-11.4744251889,2,1,18
+2025-03-11T12:39:20.389816,479392761,971,190,-8.942401908,15.41563017102,-10.42187548851,2,1,18
+2025-03-11T12:39:20.514816,479392761,971,190,-8.3305533564,14.034239044515,-9.32292767682,2,1,18
+2025-03-11T12:39:20.639816,479392761,971,190,-7.69987869552,12.61588392279,-8.246845029285,2,1,18
+2025-03-11T12:39:20.764816,479392761,971,190,-7.05508445268,11.15133798087,-7.11504707688,2,1,18
+2025-03-11T12:39:20.889816,479392761,971,190,-6.41029020984,9.663707259225,-5.955406753635,2,1,18
+2025-03-11T12:39:21.014816,479392761,971,190,-5.75608291236,8.152977584025,-4.781764035135,2,1,18
+2025-03-11T12:39:21.139816,479392761,971,190,-5.07834297828,6.62374465047,-3.60335292597,2,1,18
+2025-03-11T12:39:21.264816,479392761,971,190,-4.4006030442,5.085277805025,-2.415652915275,2,1,18
+2025-03-11T12:39:21.389816,479392761,971,190,-3.7181565828,3.53295300483,-1.21862948157,2,1,18
+2025-03-11T12:39:21.514816,479392761,971,190,-3.04041664872,1.96216746777,0.024682269555,2,1,18
+2025-03-11T12:39:21.639816,479392761,971,190,-2.35797018732,0.39599179974,1.2494994066,2,1,18
+2025-03-11T12:39:21.764816,479392761,971,190,-1.66140414396,-1.170205129035,2.45124652176,2,1,18
+2025-03-11T12:39:21.889816,479392761,971,190,-0.97425115524,-2.731770928035,3.63446845965,2,1,18
+2025-03-11T12:39:22.014740,479392765,966,191,-0.29180469384,-4.27486181634,4.83606334287,2,1,18
+2025-03-11T12:39:22.139740,479392765,966,191,0.39064176756,-5.790250968975,6.032892106575,2,1,18
+2025-03-11T12:39:22.264740,479392765,966,191,1.0354360104,-7.32405125007,7.206636118365,2,1,18
+2025-03-11T12:39:22.389740,479392765,966,191,1.6943498352,-8.82093714435,8.35711543827,2,1,18
+2025-03-11T12:39:22.514740,479392765,966,191,2.3297310234,-10.271618044605,9.470339545905,2,1,18
+2025-03-11T12:39:22.639740,479392765,966,191,2.94628610232,-11.70380277342,10.588045684635,2,1,18
+2025-03-11T12:39:22.764740,479392765,966,191,3.56754770856,-13.094441985645,11.677822305255,2,1,18
+2025-03-11T12:39:22.889740,479392765,966,191,4.17939626016,-14.4296635527,12.74418596034,2,1,18
+2025-03-11T12:39:23.014740,479392765,966,191,4.76300564784,-15.76022564232,13.745782517085,2,1,18
+2025-03-11T12:39:23.139740,479392765,966,191,5.32308239892,-17.03996578197,14.723959878855,2,1,18
+2025-03-11T12:39:23.264740,479392765,966,191,5.8596265134,-18.236565280035,15.66006724134,2,1,18
+2025-03-11T12:39:23.389740,479392765,966,191,6.35851840932,-19.400789391165,16.558961829615,2,1,18
+2025-03-11T12:39:23.514740,479392765,966,191,6.84329072328,-20.50035485832,17.42976448011,2,1,18
+2025-03-11T12:39:23.639740,479392765,966,191,7.30453040064,-21.558332287395,18.24023566701,2,1,18
+2025-03-11T12:39:23.764740,479392765,966,191,7.7422374414,-22.53778603083,19.008661188375,2,1,18
+2025-03-11T12:39:23.889740,479392765,966,191,8.14699879092,-23.46178669452,19.69356128436,2,1,18
+2025-03-11T12:39:24.014740,479392765,966,191,8.51410792188,-24.298008499935,20.35481695218,2,1,18
+2025-03-11T12:39:24.139740,479392765,966,191,8.85768441624,-25.078791399435,20.96028827217,2,1,18
+2025-03-11T12:39:24.264740,479392765,966,191,9.17302174668,-25.79951135016,21.50994072285,2,1,18
+2025-03-11T12:39:24.389740,479392765,966,191,9.44600033124,-26.40012666408,22.00342740228,2,1,18
+2025-03-11T12:39:24.514740,479392765,966,191,9.68132669724,-26.959132679175,22.418071586865,2,1,18
+2025-03-11T12:39:24.639740,479392765,966,191,9.9072400086,-27.44425322532,22.781484768825,2,1,18
+2025-03-11T12:39:24.764740,479392765,966,191,10.08608804676,-27.827729871525,23.09343944382,2,1,18
+2025-03-11T12:39:24.889740,479392765,966,191,10.22728386636,-28.141895483235,23.32640562147,2,1,18
+2025-03-11T12:39:25.014740,479392765,966,191,10.3308274674,-28.382133104505,23.51269978713,2,1,18
+2025-03-11T12:39:25.139740,479392765,966,191,10.4014253772,-28.534598954415,23.629158542205,2,1,18
+2025-03-11T12:39:25.264740,479392765,966,191,10.4484906504,-28.599307206795,23.685042496185,2,1,18
+2025-03-11T12:39:25.389740,479392765,966,191,10.4249580138,-28.59927177222,23.684991557535,2,1,18
+2025-03-11T12:39:25.514740,479392765,966,191,10.39201232256,-28.516116956805,23.6151804807,2,1,18
+2025-03-11T12:39:25.639740,479392765,966,191,10.32612094008,-28.33595645814,23.480105442795,2,1,18
+2025-03-11T12:39:25.764740,479392765,966,191,10.20845775708,-28.086463664235,23.26139122734,2,1,18
+2025-03-11T12:39:25.889740,479392765,966,191,10.0719684648,-27.75383731566,22.9913769663,2,1,18
+2025-03-11T12:39:26.014694,479392769,963,192,9.88841389932,-27.32418402309,22.68378888309,2,1,18
+2025-03-11T12:39:26.139694,479392769,963,192,9.6719136426,-26.839077650775,22.297295491515,2,1,18
+2025-03-11T12:39:26.264694,479392769,963,192,9.42717422196,-26.266206594015,21.859457345145,2,1,18
+2025-03-11T12:39:26.389694,479392769,963,192,9.1306630008,-25.61015237418,21.365627722065,2,1,18
+2025-03-11T12:39:26.514694,479392769,963,192,8.81532567036,-24.88481546751,20.797470469575,2,1,18
+2025-03-11T12:39:26.639694,479392769,963,192,8.46704264868,-24.11787634893,20.17820161206,2,1,18
+2025-03-11T12:39:26.764694,479392769,963,192,8.07640088112,-23.21698172571,19.521174450105,2,1,18
+2025-03-11T12:39:26.889694,479392769,963,192,7.66222647696,-22.30220080008,18.794721593025,2,1,18
+2025-03-11T12:39:27.014694,479392769,963,192,7.22922596352,-21.31352023167,18.01701735786,2,1,18
+2025-03-11T12:39:27.139694,479392769,963,192,6.75857323152,-20.24167776093,17.20645279425,2,1,18
+2025-03-11T12:39:27.264694,479392769,963,192,6.27380091756,-19.10979360216,16.34009992452,2,1,18
+2025-03-11T12:39:27.389694,479392769,963,192,5.75608291236,-17.922456363645,15.42718256553,2,1,18
+2025-03-11T12:39:27.514694,479392769,963,192,5.23365837984,-16.707410302545,14.49562854825,2,1,18
+2025-03-11T12:39:27.639694,479392769,963,192,4.66887510144,-15.43689698787,13.48976896416,2,1,18
+2025-03-11T12:39:27.764694,479392769,963,192,4.08997224108,-14.124809808945,12.460559228055,2,1,18
+2025-03-11T12:39:27.889694,479392769,963,192,3.49694979876,-12.748063986045,11.40325755417,2,1,18
+2025-03-11T12:39:28.014694,479392769,963,192,2.88510124716,-11.352821991705,10.327337326305,2,1,18
+2025-03-11T12:39:28.139694,479392769,963,192,2.24030700432,-9.90212691762,9.20485260918,2,1,18
+2025-03-11T12:39:28.264694,479392769,963,192,1.60963234344,-8.419134412665,8.06836776795,2,1,18
+2025-03-11T12:39:28.389694,479392769,963,192,0.941305464,-6.95455303617,6.918038408835,2,1,18
+2025-03-11T12:39:28.514694,479392769,963,192,0.27768511188,-5.43457527525,5.73970653036,2,1,18
+2025-03-11T12:39:28.639694,479392769,963,192,-0.37181565828,-3.90076790724,4.542851745765,2,1,18
+2025-03-11T12:39:28.764694,479392769,963,192,-1.04955559236,-2.33921628207,3.341169715275,2,1,18
+2025-03-11T12:39:28.889694,479392769,963,192,-1.75082816304,-0.805330957995,2.12572239759,2,1,18
+2025-03-11T12:39:29.014694,479392769,963,192,-2.46151378836,0.75627027558,0.910108701945,2,1,18
+2025-03-11T12:39:29.139694,479392769,963,192,-3.13454719512,2.32243176978,-0.291587474565,2,1,18
+2025-03-11T12:39:29.264694,479392769,963,192,-3.8122871292,3.888600350895,-1.50715418985,2,1,18
+2025-03-11T12:39:29.389694,479392769,963,192,-4.48532053596,5.436294021315,-2.722613382405,2,1,18
+2025-03-11T12:39:29.514694,479392769,963,192,-5.16776699736,6.97938490962,-3.896487563535,2,1,18
+2025-03-11T12:39:29.639694,479392769,963,192,-5.84080040412,8.49937684437,-5.070219700455,2,1,18
+2025-03-11T12:39:29.764694,479392769,963,192,-6.50912728356,10.010127780315,-6.225412514085,2,1,18
+2025-03-11T12:39:29.889694,479392769,963,192,-7.14450847176,11.48851041624,-7.37574356034,2,1,18
+2025-03-11T12:39:30.014618,479392773,958,193,-7.78459618728,12.93919840341,-8.507458323765,2,1,18
+2025-03-11T12:39:30.139618,479392773,958,193,-8.43409695744,14.357581872795,-9.615922541325,2,1,18
+2025-03-11T12:39:30.264618,479392773,958,193,-9.0365324544,15.743575781415,-10.696393843245,2,1,18
+2025-03-11T12:39:30.389618,479392773,958,193,-9.62014184208,17.06952091509,-11.7164465343,2,1,18
+2025-03-11T12:39:30.514618,479392773,958,193,-10.17551206584,18.367721791605,-12.73167197946,2,1,18
+2025-03-11T12:39:30.639618,479392773,958,193,-10.72146923496,19.62897284673,-13.705101326025,2,1,18
+2025-03-11T12:39:30.764618,479392773,958,193,-11.2721329314,20.84406142932,-14.627476235655,2,1,18
+2025-03-11T12:39:30.889618,479392773,958,193,-11.77573135464,21.989824803585,-15.52628367666,2,1,18
+2025-03-11T12:39:31.014618,479392773,958,193,-12.24167755932,23.06166018741,-16.350698403585,2,1,18
+2025-03-11T12:39:31.139618,479392773,958,193,-12.69821070936,24.10116270579,-17.13796148268,2,1,18
+2025-03-11T12:39:31.264618,479392773,958,193,-13.12650469548,25.07598531945,-17.90172217782,2,1,18
+2025-03-11T12:39:31.389618,479392773,958,193,-13.50302688108,25.958390858145,-18.586342143675,2,1,18
+2025-03-11T12:39:31.514618,479392773,958,193,-13.87484253936,26.77153497075,-19.21514551137,2,1,18
+2025-03-11T12:39:31.639618,479392773,958,193,-14.22312556104,27.52924017744,-19.79278464825,2,1,18
+2025-03-11T12:39:31.764618,479392773,958,193,-14.51022372756,28.21759891506,-20.32372516824,2,1,18
+2025-03-11T12:39:31.889618,479392773,958,193,-14.77378925748,28.81820005515,-20.79871100415,2,1,18
+2025-03-11T12:39:32.014618,479392773,958,193,-15.01852867812,29.33566764057,-21.203916326415,2,1,18
+2025-03-11T12:39:32.139618,479392773,958,193,-15.21149629824,29.81150466642,-21.56258940975,2,1,18
+2025-03-11T12:39:32.264618,479392773,958,193,-15.38093128176,30.176499315015,-21.865186140255,2,1,18
+2025-03-11T12:39:32.389618,479392773,958,193,-15.51271404672,30.46756597317,-22.088770039665,2,1,18
+2025-03-11T12:39:32.514618,479392773,958,193,-15.60684459312,30.675470728995,-22.256393025555,2,1,18
+2025-03-11T12:39:32.639618,479392773,958,193,-15.6727359756,30.79099384443,-22.340306103795,2,1,18
+2025-03-11T12:39:32.764618,479392773,958,193,-15.69156208488,30.83719175154,-22.39141147938,2,1,18
+2025-03-11T12:39:32.889618,479392773,958,193,-15.68214903024,30.804858886095,-22.358879948565,2,1,18
+2025-03-11T12:39:33.014618,479392773,958,193,-15.63979028436,30.707839029015,-22.27049502696,2,1,18
+2025-03-11T12:39:33.139618,479392773,958,193,-15.55036626528,30.509175271995,-22.126031481375,2,1,18
+2025-03-11T12:39:33.264618,479392773,958,193,-15.42799655496,30.22735669956,-21.89789650791,2,1,18
+2025-03-11T12:39:33.389618,479392773,958,193,-15.28680073536,29.85778761651,-21.61843715511,2,1,18
+2025-03-11T12:39:33.514618,479392773,958,193,-15.07971353328,29.42348193342,-21.29229333144,2,1,18
+2025-03-11T12:39:33.639618,479392773,958,193,-14.85850674924,28.91990065041,-20.868731481015,2,1,18
+2025-03-11T12:39:33.764618,479392773,958,193,-14.59964774664,28.328540509125,-20.412284968395,2,1,18
+2025-03-11T12:39:33.889618,479392773,958,193,-14.30313652548,27.658635421455,-19.890661641975,2,1,18
+2025-03-11T12:39:34.014572,479392777,955,194,-13.9783861404,26.914816517175,-19.29928609395,2,1,18
+2025-03-11T12:39:34.139572,479392777,955,194,-13.62069006408,26.09707670937,-18.69358954077,2,1,18
+2025-03-11T12:39:34.264572,479392777,955,194,-13.23475482384,25.21927395279,-18.01359365022,2,1,18
+2025-03-11T12:39:34.389572,479392777,955,194,-12.81116736504,24.253692337935,-17.28685274643,2,1,18
+2025-03-11T12:39:34.514572,479392777,955,194,-12.354634215,23.2188067755,-16.490373767055,2,1,18
+2025-03-11T12:39:34.639572,479392777,955,194,-11.883981483,22.170049084485,-15.652210170105,2,1,18
+2025-03-11T12:39:34.764572,479392777,955,194,-11.38038305976,21.028902666165,-14.76266729688,2,1,18
+2025-03-11T12:39:34.889572,479392777,955,194,-10.8720781092,19.836962645535,-13.83126551154,2,1,18
+2025-03-11T12:39:35.014572,479392777,955,194,-10.3308274674,18.603420412995,-12.876472823265,2,1,18
+2025-03-11T12:39:35.139572,479392777,955,194,-9.76133766168,17.323666099515,-11.879794617975,2,1,18
+2025-03-11T12:39:35.264572,479392777,955,194,-9.19184785596,15.988508314695,-10.84124335455,2,1,18
+2025-03-11T12:39:35.389572,479392777,955,194,-8.57999930436,14.611734144135,-9.774660695715,2,1,18
+2025-03-11T12:39:35.514572,479392777,955,194,-7.95873769812,13.188776240295,-8.69857408989,2,1,18
+2025-03-11T12:39:35.639572,479392777,955,194,-7.31394345528,11.742698122155,-7.56225335547,2,1,18
+2025-03-11T12:39:35.764572,479392777,955,194,-6.6597361578,10.268904094515,-6.430386360105,2,1,18
+2025-03-11T12:39:35.889572,479392777,955,194,-6.01494191496,8.767422505035,-5.256812684565,2,1,18
+2025-03-11T12:39:36.014572,479392777,955,194,-5.33720198088,7.252040439315,-4.06923434262,2,1,18
+2025-03-11T12:39:36.139572,479392777,955,194,-4.65475551948,5.713566506955,-2.881524144195,2,1,18
+2025-03-11T12:39:36.264572,479392777,955,194,-3.96760253076,4.14738375201,-1.661316936435,2,1,18
+2025-03-11T12:39:36.389572,479392777,955,194,-3.30398217864,2.59047034353,-0.4643099199,2,1,18
+2025-03-11T12:39:36.514572,479392777,955,194,-2.61682918992,1.01967063264,0.742061270565,2,1,18
+2025-03-11T12:39:36.639572,479392777,955,194,-1.9296762012,-0.537278210415,1.943739342765,2,1,18
+2025-03-11T12:39:36.764572,479392777,955,194,-1.23781668516,-2.094234140385,3.16852818777,2,1,18
+2025-03-11T12:39:36.889572,479392777,955,194,-0.5647832784,-3.678863458365,4.37032169928,2,1,18
+2025-03-11T12:39:37.014572,479392777,955,194,0.10825012836,-5.208089305005,5.557962854745,2,1,18
+2025-03-11T12:39:37.139572,479392777,955,194,0.78599006244,-6.70962050289,6.73622796141,2,1,18
+2025-03-11T12:39:37.264572,479392777,955,194,1.44961041456,-8.20189652814,7.905173603355,2,1,18
+2025-03-11T12:39:37.389572,479392777,955,194,2.08499160276,-9.67566220812,9.041619964815,2,1,18
+2025-03-11T12:39:37.514572,479392777,955,194,2.72507931828,-11.12635019529,10.16409449421,2,1,18
+2025-03-11T12:39:37.639572,479392777,955,194,3.34634092452,-12.535457231295,11.267828800875,2,1,18
+2025-03-11T12:39:37.764572,479392777,955,194,3.94877642148,-13.912217228025,12.31591061619,2,1,18
+2025-03-11T12:39:37.889572,479392777,955,194,4.53709233648,-15.238169448615,13.354453963035,2,1,18
+2025-03-11T12:39:38.014511,479392781,951,195,5.09716908756,-16.527143500155,14.351160460365,2,1,18
+2025-03-11T12:39:38.139511,479392781,951,195,5.64312625668,-17.76069281961,15.30596333637,2,1,18
+2025-03-11T12:39:38.264511,479392781,951,195,6.15613773456,-18.94802297121,16.195769922555,2,1,18
+2025-03-11T12:39:38.389511,479392781,951,195,6.6597361578,-20.075318521695,17.06675932647,2,1,18
+2025-03-11T12:39:38.514511,479392781,951,195,7.14450847176,-21.13794834129,17.90502648786,2,1,18
+2025-03-11T12:39:38.639511,479392781,951,195,7.5775089852,-22.15433064537,18.68749684254,2,1,18
+2025-03-11T12:39:38.764511,479392781,951,195,7.98697686204,-23.09218926381,19.427921531685,2,1,18
+2025-03-11T12:39:38.889511,479392781,951,195,8.37291210228,-23.95152419661,20.10319997022,2,1,18
+2025-03-11T12:39:39.014511,479392781,951,195,8.72590165128,-24.76002300561,20.72731813623,2,1,18
+2025-03-11T12:39:39.139511,479392781,951,195,9.04594550904,-25.48998395514,21.28626967617,2,1,18
+2025-03-11T12:39:39.264511,479392781,951,195,9.35657631216,-26.150676391665,21.79863466425,2,1,18
+2025-03-11T12:39:39.389511,479392781,951,195,9.59190267816,-26.732767186485,22.25498157072,2,1,18
+2025-03-11T12:39:39.514511,479392781,951,195,9.82252251684,-27.245596555215,22.646271645,2,1,18
+2025-03-11T12:39:39.639511,479392781,951,195,10.01549013696,-27.684497933505,22.98164947326,2,1,18
+2025-03-11T12:39:39.764511,479392781,951,195,10.17080553852,-28.02638654163,23.26099338675,2,1,18
+2025-03-11T12:39:39.889511,479392781,951,195,10.29317524884,-28.28512033434,23.45666587236,2,1,18
+2025-03-11T12:39:40.014511,479392781,951,195,10.38259926792,-28.47455017947,23.59646063343,2,1,18
+2025-03-11T12:39:40.139511,479392781,951,195,10.4249580138,-28.585420904385,23.675678322255,2,1,18
+2025-03-11T12:39:40.264511,479392781,951,195,10.44378412308,-28.613150987715,23.70820589478,2,1,18
+2025-03-11T12:39:40.389511,479392781,951,195,10.41554495916,-28.566938906775,23.666320377765,2,1,18
+2025-03-11T12:39:40.514511,479392781,951,195,10.34024052204,-28.419082925895,23.55911600274,2,1,18
+2025-03-11T12:39:40.639511,479392781,951,195,10.236696921,-28.188079216515,23.386730855625,2,1,18
+2025-03-11T12:39:40.764511,479392781,951,195,10.10491415604,-27.883161690525,23.144593486905,2,1,18
+2025-03-11T12:39:40.889511,479392781,951,195,9.94959875448,-27.508954390785,22.837358535075,2,1,18
+2025-03-11T12:39:41.014511,479392781,951,195,9.75192460704,-27.06081201369,22.474201149495,2,1,18
+2025-03-11T12:39:41.139511,479392781,951,195,9.49306560444,-26.51100447591,22.064174810775,2,1,18
+2025-03-11T12:39:41.264511,479392781,951,195,9.2247935472,-25.8688436454,21.579719549355,2,1,18
+2025-03-11T12:39:41.389511,479392781,951,195,8.92828232604,-25.17123682206,21.030229518345,2,1,18
+2025-03-11T12:39:41.514511,479392781,951,195,8.60823846828,-24.43204196064,20.44812872583,2,1,18
+2025-03-11T12:39:41.639511,479392781,951,195,8.23171628268,-23.586572069505,19.81452471714,2,1,18
+2025-03-11T12:39:41.764511,479392781,951,195,7.82695493316,-22.699507053375,19.102098589065,2,1,18
+2025-03-11T12:39:41.889511,479392781,951,195,7.39395441972,-21.720060396855,18.347543606475,2,1,18
+2025-03-11T12:39:42.014435,479392785,946,196,6.93742126968,-20.69440874631,17.54187306057,2,1,18
+2025-03-11T12:39:42.139435,479392785,946,196,6.45735548304,-19.599467322015,16.689585399615,2,1,18
+2025-03-11T12:39:42.264435,479392785,946,196,5.96317011444,-18.439867253745,15.79996556685,2,1,18
+2025-03-11T12:39:42.389435,479392785,946,196,5.4360390546,-17.229431061675,14.86842569559,2,1,18
+2025-03-11T12:39:42.514435,479392785,946,196,4.88537535816,-15.968172919635,13.89960627831,2,1,18
+2025-03-11T12:39:42.639435,479392785,946,196,4.31588555244,-14.65609991454,12.879657151695,2,1,18
+2025-03-11T12:39:42.764435,479392785,946,196,3.7181565828,-13.32089960823,11.836424644875,2,1,18
+2025-03-11T12:39:42.889435,479392785,946,196,3.11101455852,-11.934898612695,10.75132303821,2,1,18
+2025-03-11T12:39:43.014435,479392785,946,196,2.47563337032,-10.48421771244,9.665819632665,2,1,18
+2025-03-11T12:39:43.139435,479392785,946,196,1.82613260016,-9.028898595495,8.557160745105,2,1,18
+2025-03-11T12:39:43.264435,479392785,946,196,1.18604488464,-7.54589191671,7.374454358265,2,1,18
+2025-03-11T12:39:43.389435,479392785,946,196,0.52713105984,-6.035155154595,6.191561218005,2,1,18
+2025-03-11T12:39:43.514435,479392785,946,196,-0.14590234692,-4.524397131735,5.017877748585,2,1,18
+2025-03-11T12:39:43.639435,479392785,946,196,-0.80481617172,-2.99519254584,3.83026715631,2,1,18
+2025-03-11T12:39:43.764435,479392785,946,196,-1.4825561058,-1.429023964725,2.623940675055,2,1,18
+2025-03-11T12:39:43.889435,479392785,946,196,-2.17441562184,0.13254892119,1.41760796436,2,1,18
+2025-03-11T12:39:44.014435,479392785,946,196,-2.85215555592,1.689483590415,0.202089916575,2,1,18
+2025-03-11T12:39:44.139435,479392785,946,196,-3.53460201732,3.255659258445,-1.01348698644,2,1,18
+2025-03-11T12:39:44.264435,479392785,946,196,-4.23116806068,4.81262227533,-2.22442566813,2,1,18
+2025-03-11T12:39:44.389435,479392785,946,196,-4.90890799476,6.35570607672,-3.40752989556,2,1,18
+2025-03-11T12:39:44.514435,479392785,946,196,-5.57252834688,7.89415166142,-4.59981946008,2,1,18
+2025-03-11T12:39:44.639435,479392785,946,196,-6.23144217168,9.414122335425,-5.768900916795,2,1,18
+2025-03-11T12:39:44.764435,479392785,946,196,-6.90918210576,10.911036577365,-6.933281338665,2,1,18
+2025-03-11T12:39:44.889435,479392785,946,196,-7.53985676664,12.37556125854,-8.069668844895,2,1,18
+2025-03-11T12:39:45.014435,479392785,946,196,-8.16111837288,13.793902206435,-9.178071936075,2,1,18
+2025-03-11T12:39:45.139435,479392785,946,196,-8.77296692448,15.19376115672,-10.27249696575,2,1,18
+2025-03-11T12:39:45.264435,479392785,946,196,-9.38010894876,16.53820954875,-11.32503874956,2,1,18
+2025-03-11T12:39:45.389435,479392785,946,196,-9.96371833644,17.854920770535,-12.326562305055,2,1,18
+2025-03-11T12:39:45.514435,479392785,946,196,-10.53320814216,19.143908995905,-13.31866906083,2,1,18
+2025-03-11T12:39:45.639435,479392785,946,196,-11.05563267468,20.368188968895,-14.25951197964,2,1,18
+2025-03-11T12:39:45.764435,479392785,946,196,-11.56393762524,21.5370442098,-15.15383116011,2,1,18
+2025-03-11T12:39:45.889435,479392785,946,196,-12.05812299384,22.62277298295,-16.01072083377,2,1,18
+2025-03-11T12:39:46.014358,479392789,941,197,-12.50994961656,23.653034502525,-16.83026587674,2,1,18
+2025-03-11T12:39:46.139358,479392789,941,197,-12.93824360268,24.664792763745,-17.589601124865,2,1,18
+2025-03-11T12:39:46.264358,479392789,941,197,-13.35241800684,25.59342455721,-18.31150686618,2,1,18
+2025-03-11T12:39:46.389358,479392789,941,197,-13.74776630172,26.438922796005,-18.97287232788,2,1,18
+2025-03-11T12:39:46.514358,479392789,941,197,-14.08192974144,27.238159345455,-19.56918037338,2,1,18
+2025-03-11T12:39:46.639358,479392789,941,197,-14.41609318116,27.93120590817,-20.123347689495,2,1,18
+2025-03-11T12:39:46.764358,479392789,941,197,-14.69848482036,28.591855823205,-20.63103143418,2,1,18
+2025-03-11T12:39:46.889358,479392789,941,197,-14.93381118636,29.155478794245,-21.05956030356,2,1,18
+2025-03-11T12:39:47.014358,479392789,941,197,-15.15031144308,29.635968210615,-21.44140924437,2,1,18
+2025-03-11T12:39:47.139358,479392789,941,197,-15.3197464266,30.051749374605,-21.753513880155,2,1,18
+2025-03-11T12:39:47.264358,479392789,941,197,-15.46564877352,30.37515598512,-22.005019381095,2,1,18
+2025-03-11T12:39:47.389358,479392789,941,197,-15.58801848384,30.610804998105,-22.209810431985,2,1,18
+2025-03-11T12:39:47.514358,479392789,941,197,-15.66332292096,30.78174575871,-22.32637670979,2,1,18
+2025-03-11T12:39:47.639358,479392789,941,197,-15.69156208488,30.869510443155,-22.39158181563,2,1,18
+2025-03-11T12:39:47.764358,479392789,941,197,-15.70568166684,30.855680836065,-22.4007796116,2,1,18
+2025-03-11T12:39:47.889358,479392789,941,197,-15.67744250292,30.7863839754,-22.331051723745,2,1,18
+2025-03-11T12:39:48.014358,479392789,941,197,-15.59272501116,30.606195129075,-22.191315817905,2,1,18
+2025-03-11T12:39:48.139358,479392789,941,197,-15.47035530084,30.356695248255,-22.014172467855,2,1,18
+2025-03-11T12:39:48.264358,479392789,941,197,-15.33386600856,30.01483498779,-21.74872965633,2,1,18
+2025-03-11T12:39:48.389358,479392789,941,197,-15.15972449772,29.6313654285,-21.436785169065,2,1,18
+2025-03-11T12:39:48.514358,479392789,941,197,-14.94793076832,29.13703223121,-21.06873376578,2,1,18
+2025-03-11T12:39:48.639358,479392789,941,197,-14.69377829304,28.57338091251,-20.63092391145,2,1,18
+2025-03-11T12:39:48.764358,479392789,941,197,-14.41138665384,27.940432733145,-20.123386169265,2,1,18
+2025-03-11T12:39:48.889358,479392789,941,197,-14.10546237804,27.21972695625,-19.564513860015,2,1,18
+2025-03-11T12:39:49.014358,479392789,941,197,-13.77600546564,26.44358227344,-18.96371755398,2,1,18
+2025-03-11T12:39:49.139358,479392789,941,197,-13.40418980736,25.575034689495,-18.29304112815,2,1,18
+2025-03-11T12:39:49.264358,479392789,941,197,-12.99472193052,24.65102693889,-17.580410142345,2,1,18
+2025-03-11T12:39:49.389358,479392789,941,197,-12.57113447172,23.666977500255,-16.798130499375,2,1,18
+2025-03-11T12:39:49.514358,479392789,941,197,-12.11460132168,22.609007158095,-15.978429266175,2,1,18
+2025-03-11T12:39:49.639358,479392789,941,197,-11.62982900772,21.50944169094,-15.130727200755,2,1,18
+2025-03-11T12:39:49.764358,479392789,941,197,-11.11681752984,20.33134545123,-14.20400834595,2,1,18
+2025-03-11T12:39:49.889358,479392789,941,197,-10.58027341536,19.10242726155,-13.2631105302,2,1,18
+2025-03-11T12:39:50.014312,479392793,938,198,-10.02960971892,17.82270129573,-12.27571330986,2,1,18
+2025-03-11T12:39:50.139312,479392793,938,198,-9.44129380392,16.50598298703,-11.255699098575,2,1,18
+2025-03-11T12:39:50.264312,479392793,938,198,-8.83885830696,15.133839946245,-10.20764161701,2,1,18
+2025-03-11T12:39:50.389312,479392793,938,198,-8.22700975536,13.73398099596,-9.122456821365,2,1,18
+2025-03-11T12:39:50.514312,479392793,938,198,-7.6010416218,12.301782093315,-8.023210775235,2,1,18
+2025-03-11T12:39:50.639312,479392793,938,198,-6.96095390628,10.860328018035,-6.89154467931,2,1,18
+2025-03-11T12:39:50.764312,479392793,938,198,-6.30204008148,9.3680590797,-5.731849459125,2,1,18
+2025-03-11T12:39:50.889312,479392793,938,198,-5.62900667472,7.843450189005,-4.567333222485,2,1,18
+2025-03-11T12:39:51.014312,479392793,938,198,-4.96067979528,6.32346534117,-3.393611273295,2,1,18
+2025-03-11T12:39:51.139312,479392793,938,198,-4.27823333388,4.76652358503,-2.18732327181,2,1,18
+2025-03-11T12:39:51.264312,479392793,938,198,-3.6004933998,3.19573804797,-0.96711210576,2,1,18
+2025-03-11T12:39:51.389312,479392793,938,198,-2.92275346572,1.657271202525,0.24368849001,2,1,18
+2025-03-11T12:39:51.514312,479392793,938,198,-2.22618742236,0.086457317805,1.450080055935,2,1,18
+2025-03-11T12:39:51.639312,479392793,938,198,-1.54844748828,-1.47047735142,2.65635786969,2,1,18
+2025-03-11T12:39:51.764312,479392793,938,198,-0.86600102688,-3.02741910756,3.853405637145,2,1,18
+2025-03-11T12:39:51.889312,479392793,938,198,-0.18355456548,-4.57512695181,5.064265088145,2,1,18
+2025-03-11T12:39:52.014312,479392793,938,198,0.48947884128,-6.099735842505,6.24264167583,2,1,18
+2025-03-11T12:39:52.139312,479392793,938,198,1.14368613876,-7.591997693925,7.411566942315,2,1,18
+2025-03-11T12:39:52.264312,479392793,938,198,1.8120130182,-9.0750468942,8.56199363643,2,1,18
+2025-03-11T12:39:52.389312,479392793,938,198,2.4473942064,-10.54881257418,9.684579646845,2,1,18
+2025-03-11T12:39:52.514312,479392793,938,198,3.0827753946,-11.97640869471,10.802302202745,2,1,18
+2025-03-11T12:39:52.639312,479392793,938,198,3.68521089156,-13.339317823605,11.873411601885,2,1,18
+2025-03-11T12:39:52.764312,479392793,938,198,4.27352680656,-14.683737867975,12.907432166715,2,1,18
+2025-03-11T12:39:52.889312,479392793,938,198,4.8477231396,-15.995817959985,13.932011598075,2,1,18
+2025-03-11T12:39:53.014312,479392793,938,198,5.39368030872,-17.270919882945,14.88703347783,2,1,18
+2025-03-11T12:39:53.139312,479392793,938,198,5.92551789588,-18.47212925004,15.823154986335,2,1,18
+2025-03-11T12:39:53.264312,479392793,938,198,6.43852937376,-19.6040559303,16.71266956752,2,1,18
+2025-03-11T12:39:53.389312,479392793,938,198,6.92800821504,-20.708245440315,17.565026271435,2,1,18
+2025-03-11T12:39:53.514312,479392793,938,198,7.37983483776,-21.73850695989,18.366090846345,2,1,18
+2025-03-11T12:39:53.639312,479392793,938,198,7.79400924192,-22.704074400915,19.120532076765,2,1,18
+2025-03-11T12:39:53.764312,479392793,938,198,8.19877059144,-23.600373328935,19.81452640428,2,1,18
+2025-03-11T12:39:53.889312,479392793,938,198,8.57058624972,-24.4504530891,20.452764676005,2,1,18
+2025-03-11T12:39:54.014236,479392797,933,199,8.90945621676,-25.203527166015,21.058079805765,2,1,18
+2025-03-11T12:39:54.139236,479392797,933,199,9.20596743792,-25.89651703341,21.598305268995,2,1,18
+2025-03-11T12:39:54.264236,479392797,933,199,9.47423949516,-26.524826996085,22.05034671006,2,1,18
+2025-03-11T12:39:54.389236,479392797,933,199,9.70956586116,-27.0653651874,22.47875391069,2,1,18
+2025-03-11T12:39:54.514236,479392797,933,199,9.92135959056,-27.52276273713,22.828130175915,2,1,18
+2025-03-11T12:39:54.639236,479392797,933,199,10.08138151944,-27.896977123785,23.126135081445,2,1,18
+2025-03-11T12:39:54.764236,479392797,933,199,10.2131642844,-28.211128561665,23.35446076662,2,1,18
+2025-03-11T12:39:54.889236,479392797,933,199,10.31670788544,-28.42828140321,23.526772912485,2,1,18
+2025-03-11T12:39:55.014236,479392797,933,199,10.38259926792,-28.56688929837,23.64314847858,2,1,18
+2025-03-11T12:39:55.139236,479392797,933,199,10.40613190452,-28.631562116175,23.68974125988,2,1,18
+2025-03-11T12:39:55.264236,479392797,933,199,10.4014253772,-28.58538546981,23.675627383605,2,1,18
+2025-03-11T12:39:55.389236,479392797,933,199,10.34965357668,-28.483734482955,23.591817869805,2,1,18
+2025-03-11T12:39:55.514236,479392797,933,199,10.25552303028,-28.289680594965,23.44736847024,2,1,18
+2025-03-11T12:39:55.639236,479392797,933,199,10.15197942924,-28.030975149915,23.228636150475,2,1,18
+2025-03-11T12:39:55.764236,479392797,933,199,10.01078360964,-27.679873890645,22.94465401566,2,1,18
+2025-03-11T12:39:55.889236,479392797,933,199,9.83193557148,-27.254844640935,22.60013951781,2,1,18
+2025-03-11T12:39:56.014236,479392797,933,199,9.60602226012,-26.737405403175,22.19959506348,2,1,18
+2025-03-11T12:39:56.139236,479392797,933,199,9.3424567302,-26.13218730714,21.747685478895,2,1,18
+2025-03-11T12:39:56.264236,479392797,933,199,9.05535856368,-25.466913349245,21.25844768079,2,1,18
+2025-03-11T12:39:56.389236,479392797,933,199,8.74002123324,-24.750810354465,20.67185862774,2,1,18
+2025-03-11T12:39:56.514236,479392797,933,199,8.38703168424,-23.942311545465,20.043120344715,2,1,18
+2025-03-11T12:39:56.639236,479392797,933,199,7.99638991668,-23.06450170197,19.363114266435,2,1,18
+2025-03-11T12:39:56.764236,479392797,933,199,7.59162856716,-22.11279930261,18.627246880785,2,1,18
+2025-03-11T12:39:56.889236,479392797,933,199,7.1539215264,-21.105643823505,17.83095465483,2,1,18
+2025-03-11T12:39:57.014236,479392797,933,199,6.67856226708,-20.03379426585,17.02037990349,2,1,18
+2025-03-11T12:39:57.139236,479392797,933,199,6.17967037116,-18.901888846335,16.14475623654,2,1,18
+2025-03-11T12:39:57.264236,479392797,933,199,5.65724583864,-17.714544520905,15.227208572805,2,1,18
+2025-03-11T12:39:57.389236,479392797,933,199,5.11599519684,-16.471768376475,14.267747100015,2,1,18
+2025-03-11T12:39:57.514236,479392797,933,199,4.55121191844,-15.19202114991,13.27569919947,2,1,18
+2025-03-11T12:39:57.639236,479392797,933,199,3.96760253076,-13.875309928125,12.246454941885,2,1,18
+2025-03-11T12:39:57.764236,479392797,933,199,3.36987356112,-12.5077909302,11.184571630755,2,1,18
+2025-03-11T12:39:57.889236,479392797,933,199,2.74390542756,-11.08944289539,10.09001870289,2,1,18
+2025-03-11T12:39:58.014175,479392801,929,200,2.12264382132,-9.65725107966,8.967682259415,2,1,18
+2025-03-11T12:39:58.139175,479392801,929,200,1.47784957848,-8.188088181795,7.84510020729,2,1,18
+2025-03-11T12:39:58.264175,479392801,929,200,0.823642281,-6.677358506595,6.68069772282,2,1,18
+2025-03-11T12:39:58.389175,479392801,929,200,0.14590234692,-5.15735948493,5.49771516414,2,1,18
+2025-03-11T12:39:58.514175,479392801,929,200,-0.52242453252,-3.618906813315,4.300795294875,2,1,18
+2025-03-11T12:39:58.639175,479392801,929,200,-1.21428404856,-2.0573339274,3.10370281821,2,1,18
+2025-03-11T12:39:58.764175,479392801,929,200,-1.90143703728,-0.518852908125,1.897501963995,2,1,18
+2025-03-11T12:39:58.889175,479392801,929,200,-2.57917697136,1.051932628935,0.68191091496,2,1,18
+2025-03-11T12:39:59.014175,479392801,929,200,-3.25691690544,2.63656903383,-0.52913301831,2,1,18
+2025-03-11T12:39:59.139175,479392801,929,200,-3.94877642148,4.188908007855,-1.735417061505,2,1,18
+2025-03-11T12:39:59.264175,479392801,929,200,-4.62651635556,5.74584267708,-2.927834524215,2,1,18
+2025-03-11T12:39:59.389175,479392801,929,200,-5.30896281696,7.28431660944,-4.120164839655,2,1,18
+2025-03-11T12:39:59.514175,479392801,929,200,-5.96317011444,8.80428019653,-5.3077165767,2,1,18
+2025-03-11T12:39:59.639175,479392801,929,200,-6.62208393924,10.29193217892,-6.47200758015,2,1,18
+2025-03-11T12:39:59.764175,479392801,929,200,-7.27629123672,11.751875338725,-7.622282042325,2,1,18
+2025-03-11T12:39:59.889175,479392801,929,200,-7.9304985342,13.216435454475,-8.73561990213,2,1,18
+2025-03-11T12:40:00.014175,479392801,929,200,-8.53764055848,14.63937209757,-9.839396646855,2,1,18
+2025-03-11T12:40:00.139175,479392801,929,200,-9.12595647348,16.00225996572,-10.90585536579,2,1,18
+2025-03-11T12:40:00.264175,479392801,929,200,-9.72839197044,17.328233447055,-11.93980915881,2,1,18
+2025-03-11T12:40:00.389175,479392801,929,200,-10.29788177616,18.617221672425,-12.92729579757,2,1,18
+2025-03-11T12:40:00.514175,479392801,929,200,-10.83442589064,19.873841597775,-13.882199966865,2,1,18
+2025-03-11T12:40:00.639175,479392801,929,200,-11.34743736852,21.051937837485,-14.79967858764,2,1,18
+2025-03-11T12:40:00.764175,479392801,929,200,-11.85103579176,22.193084255805,-15.679981226835,2,1,18
+2025-03-11T12:40:00.889175,479392801,929,200,-12.34522116036,23.26496216112,-16.5229375482,2,1,18
+2025-03-11T12:40:01.014175,479392801,929,200,-12.79704778308,24.28137281286,-17.300828536785,2,1,18
+2025-03-11T12:40:01.139175,479392801,929,200,-13.20651565992,25.223848387245,-18.02279709162,2,1,18
+2025-03-11T12:40:01.264175,479392801,929,200,-13.59715742748,26.124743010465,-18.71216507268,2,1,18
+2025-03-11T12:40:01.389175,479392801,929,200,-13.95956003112,26.93787294924,-19.3363279479,2,1,18
+2025-03-11T12:40:01.514175,479392801,929,200,-14.27960388888,27.681684766605,-19.92307319118,2,1,18
+2025-03-11T12:40:01.639175,479392801,929,200,-14.57611511004,28.34697289833,-20.458532534895,2,1,18
+2025-03-11T12:40:01.764175,479392801,929,200,-14.8490936946,28.94758821225,-20.91043816119,2,1,18
+2025-03-11T12:40:01.889175,479392801,929,200,-15.07971353328,29.474268448815,-21.297181119705,2,1,18
+2025-03-11T12:40:02.014114,479392805,925,201,-15.26797462608,29.908545784245,-21.61866407544,2,1,18
+2025-03-11T12:40:02.139114,479392805,925,201,-15.41858350032,30.24581034951,-21.87949299939,2,1,18
+2025-03-11T12:40:02.264114,479392805,925,201,-15.55036626528,30.509175271995,-22.107551013315,2,1,18
+2025-03-11T12:40:02.389114,479392805,925,201,-15.63508375704,30.7078319421,-22.27048483923,2,1,18
+2025-03-11T12:40:02.514114,479392805,925,201,-15.68214903024,30.80947584204,-22.358904282315,2,1,18
+2025-03-11T12:40:02.639114,479392805,925,201,-15.70097513952,30.851056793205,-22.386884739075,2,1,18
+2025-03-11T12:40:02.764114,479392805,925,201,-15.68214903024,30.795624974205,-22.349591047035,2,1,18
+2025-03-11T12:40:02.889114,479392805,925,201,-15.62096417508,30.65702416596,-22.247086019715,2,1,18
+2025-03-11T12:40:03.014114,479392805,925,201,-15.52212710136,30.467580147,-22.079550181095,2,1,18
+2025-03-11T12:40:03.139114,479392805,925,201,-15.38563780908,30.15803857815,-21.86047887597,2,1,18
+2025-03-11T12:40:03.264114,479392805,925,201,-15.23032240752,29.797682146245,-21.567177276435,2,1,18
+2025-03-11T12:40:03.389114,479392805,925,201,-15.02794173276,29.3356818144,-21.222417169935,2,1,18
+2025-03-11T12:40:03.514114,479392805,925,201,-14.8020284214,28.795157796915,-20.794030344765,2,1,18
+2025-03-11T12:40:03.639114,479392805,925,201,-14.54787594612,28.18995387471,-20.31442043355,2,1,18
+2025-03-11T12:40:03.764114,479392805,925,201,-14.23253861568,27.51078652749,-19.788087571695,2,1,18
+2025-03-11T12:40:03.889114,479392805,925,201,-13.89366864864,26.76232940652,-19.20589736076,2,1,18
+2025-03-11T12:40:04.014114,479392805,925,201,-13.54538562696,25.93075290471,-18.56318724567,2,1,18
+2025-03-11T12:40:04.139114,479392805,925,201,-13.16415691404,25.03910636721,-17.85540783951,2,1,18
+2025-03-11T12:40:04.264114,479392805,925,201,-12.7311564006,24.055042754745,-17.1100687572,2,1,18
+2025-03-11T12:40:04.389114,479392805,925,201,-12.2840363052,23.02017136614,-16.332090621345,2,1,18
+2025-03-11T12:40:04.514114,479392805,925,201,-11.80397051856,21.94831472157,-15.493784980185,2,1,18
+2025-03-11T12:40:04.639114,479392805,925,201,-11.295665568,20.797927304445,-14.608803368745,2,1,18
+2025-03-11T12:40:04.764114,479392805,925,201,-10.7779475628,19.615207021875,-13.686670109475,2,1,18
+2025-03-11T12:40:04.889114,479392805,925,201,-10.22257733904,18.367792660755,-12.7132933887,2,1,18
+2025-03-11T12:40:05.014114,479392805,925,201,-9.648381006,17.06956343658,-11.702647309635,2,1,18
+2025-03-11T12:40:05.139114,479392805,925,201,-9.060065091,15.720526436265,-10.659362177025,2,1,18
+2025-03-11T12:40:05.264114,479392805,925,201,-8.4482165394,14.325284441925,-9.5649614811,2,1,18
+2025-03-11T12:40:05.389114,479392805,925,201,-7.8363679878,12.91619157975,-8.479728017955,2,1,18
+2025-03-11T12:40:05.514114,479392805,925,201,-7.19628027228,11.45626968069,-7.36644505509,2,1,18
+2025-03-11T12:40:05.639114,479392805,925,201,-6.5420729748,9.97324174116,-6.216048924165,2,1,18
+2025-03-11T12:40:05.764114,479392805,925,201,-5.88315915,8.471738890935,-5.04706480245,2,1,18
+2025-03-11T12:40:05.889114,479392805,925,201,-5.2007126886,6.951732782355,-3.868692173055,2,1,18
+2025-03-11T12:40:06.014053,479392809,921,202,-4.5182662272,5.39940798216,-2.667048622335,2,1,18
+2025-03-11T12:40:06.139053,479392809,921,202,-3.84993934776,3.83787053082,-1.45152661626,2,1,18
+2025-03-11T12:40:06.264053,479392809,921,202,-3.16749288636,2.285545730625,-0.23140259748,2,1,18
+2025-03-11T12:40:06.389053,479392809,921,202,-2.47563337032,0.72397284471,0.97955023023,2,1,18
+2025-03-11T12:40:06.514053,479392809,921,202,-1.79789343624,-0.832961824515,2.18120792697,2,1,18
+2025-03-11T12:40:06.639053,479392809,921,202,-1.11544697484,-2.40375444849,3.396809163735,2,1,18
+2025-03-11T12:40:06.764053,479392809,921,202,-0.43770704076,-3.95607216177,4.58458217568,2,1,18
+2025-03-11T12:40:06.889053,479392809,921,202,0.2588590026,-5.48071648704,5.772249936045,2,1,18
+2025-03-11T12:40:07.014053,479392809,921,202,0.92718588204,-6.98685046704,6.95975923503,2,1,18
+2025-03-11T12:40:07.139053,479392809,921,202,1.56727359756,-8.469857145825,8.110124802765,2,1,18
+2025-03-11T12:40:07.264053,479392809,921,202,2.20265478576,-9.925155002025,9.237233595195,2,1,18
+2025-03-11T12:40:07.389053,479392809,921,202,2.85215555592,-11.375857163025,10.345868149005,2,1,18
+2025-03-11T12:40:07.514053,479392809,921,202,3.47341716216,-12.78496419903,11.43112198761,2,1,18
+2025-03-11T12:40:07.639053,479392809,921,202,4.0476134952,-14.157064718325,12.488358576825,2,1,18
+2025-03-11T12:40:07.764053,479392809,921,202,4.64063593752,-15.47379011394,13.50838297584,2,1,18
+2025-03-11T12:40:07.889053,479392809,921,202,5.19600616128,-16.753523166675,14.50503061794,2,1,18
+2025-03-11T12:40:08.014053,479392809,921,202,5.7419633304,-17.982455530185,15.441328692135,2,1,18
+2025-03-11T12:40:08.139053,479392809,921,202,6.25497480828,-19.151317858005,16.34951841138,2,1,18
+2025-03-11T12:40:08.264053,479392809,921,202,6.7538667042,-20.269372409685,17.220448960065,2,1,18
+2025-03-11T12:40:08.389053,479392809,921,202,7.21510638156,-21.331966794705,18.04480483176,2,1,18
+2025-03-11T12:40:08.514053,479392809,921,202,7.64340036768,-22.3206402762,18.831739113225,2,1,18
+2025-03-11T12:40:08.639053,479392809,921,202,8.05286824452,-23.24003107086,19.54434576528,2,1,18
+2025-03-11T12:40:08.764053,479392809,921,202,8.43409695744,-24.0947419608,20.201109214275,2,1,18
+2025-03-11T12:40:08.889053,479392809,921,202,8.79179303376,-24.90786481266,20.806781433705,2,1,18
+2025-03-11T12:40:09.014053,479392809,921,202,9.1071303642,-25.63320171933,21.37031856918,2,1,18
+2025-03-11T12:40:09.139053,479392809,921,202,9.39893505804,-26.28924885225,21.86413800453,2,1,18
+2025-03-11T12:40:09.264053,479392809,921,202,9.63896795136,-26.85749586615,22.30194162942,2,1,18
+2025-03-11T12:40:09.389053,479392809,921,202,9.84134862612,-27.35181488961,22.688453125305,2,1,18
+2025-03-11T12:40:09.514053,479392809,921,202,10.01549013696,-27.739901404845,23.01890241438,2,1,18
+2025-03-11T12:40:09.639053,479392809,921,202,10.18492512048,-28.072577361825,23.2797477555,2,1,18
+2025-03-11T12:40:09.764053,479392809,921,202,10.2837621942,-28.33127571996,23.479989419475,2,1,18
+2025-03-11T12:40:09.889053,479392809,921,202,10.36377315864,-28.506840523425,23.628931037865,2,1,18
+2025-03-11T12:40:10.013992,479392813,917,203,10.41554495916,-28.61772542217,23.694308751105,2,1,18
+2025-03-11T12:40:10.138992,479392813,917,203,10.42025148648,-28.636200332865,23.69903639085,2,1,18
+2025-03-11T12:40:10.263992,479392813,917,203,10.38259926792,-28.534570606755,23.629117791285,2,1,18
+2025-03-11T12:40:10.388992,479392813,917,203,10.31200135812,-28.38672171279,23.508063252945,2,1,18
+2025-03-11T12:40:10.513992,479392813,917,203,10.20845775708,-28.141867135575,23.330984987565,2,1,18
+2025-03-11T12:40:10.638992,479392813,917,203,10.07667499212,-27.809247873915,23.08408149933,2,1,18
+2025-03-11T12:40:10.763992,479392813,917,203,9.89312042664,-27.416530228905,22.781308203135,2,1,18
+2025-03-11T12:40:10.888992,479392813,917,203,9.70015280652,-26.945310159,22.418039336535,2,1,18
+2025-03-11T12:40:11.013992,479392813,917,203,9.45541338588,-26.377056058185,21.9756054069,2,1,18
+2025-03-11T12:40:11.138992,479392813,917,203,9.17302174668,-25.75334179071,21.48197668326,2,1,18
+2025-03-11T12:40:11.263992,479392813,917,203,8.8718039982,-25.055727880455,20.927856347505,2,1,18
+2025-03-11T12:40:11.388992,479392813,917,203,8.53293403116,-24.288802935705,20.322468216495,2,1,18
+2025-03-11T12:40:11.513992,479392813,917,203,8.16111837288,-23.415638395815,19.651767456915,2,1,18
+2025-03-11T12:40:11.638992,479392813,917,203,7.75635702336,-22.50548859996,18.943839777105,2,1,18
+2025-03-11T12:40:11.763992,479392813,917,203,7.32335650992,-21.521424987495,18.19388057778,2,1,18
+2025-03-11T12:40:11.888992,479392813,917,203,6.86211683256,-20.47268147031,17.36497759032,2,1,18
+2025-03-11T12:40:12.013992,479392813,917,203,6.37263799128,-19.37310891624,16.521885454185,2,1,18
+2025-03-11T12:40:12.138992,479392813,917,203,5.86903956804,-18.20426076225,15.627576461445,2,1,18
+2025-03-11T12:40:12.263992,479392813,917,203,5.34661503552,-16.98921470115,14.68216209312,2,1,18
+2025-03-11T12:40:12.388992,479392813,917,203,4.8006578664,-15.75104842575,13.68575383023,2,1,18
+2025-03-11T12:40:12.513992,479392813,917,203,4.20763542408,-14.452790853915,12.67044688323,2,1,18
+2025-03-11T12:40:12.638992,479392813,917,203,3.6240260364,-13.0714422489,11.63624183613,2,1,18
+2025-03-11T12:40:12.763992,479392813,917,203,3.0121774848,-11.671583298615,10.551057040485,2,1,18
+2025-03-11T12:40:12.888992,479392813,917,203,2.3767962966,-10.253221089975,9.433383152085,2,1,18
+2025-03-11T12:40:13.013992,479392813,917,203,1.74612163572,-8.793313364745,8.287779745575,2,1,18
+2025-03-11T12:40:13.138992,479392813,917,203,1.10132739288,-7.29644873121,7.141951105875,2,1,18
+2025-03-11T12:40:13.263992,479392813,917,203,0.41888093148,-5.79491044641,5.968295928495,2,1,18
+2025-03-11T12:40:13.388992,479392813,917,203,-0.24944594796,-4.265691686685,4.78990519479,2,1,18
+2025-03-11T12:40:13.513992,479392813,917,203,-0.9177728274,-2.722622059125,3.59758110879,2,1,18
+2025-03-11T12:40:13.638992,479392813,917,203,-1.60963234344,-1.156432217265,2.38660394733,2,1,18
+2025-03-11T12:40:13.763992,479392813,917,203,-2.29678533216,0.41898444957,1.180208423115,2,1,18
+2025-03-11T12:40:13.888992,479392813,917,203,-2.97923179356,1.980543161655,-0.03534414615,2,1,18
+2025-03-11T12:40:14.013916,479392817,912,204,-3.66638478228,3.523641136875,-1.2369492171,2,1,18
+2025-03-11T12:40:14.138916,479392817,912,204,-4.353537771,5.09905780371,-2.443344741315,2,1,18
+2025-03-11T12:40:14.263916,479392817,912,204,-5.04069075972,6.65138969082,-3.64961859678,2,1,18
+2025-03-11T12:40:14.388916,479392817,912,204,-5.69960458452,8.180594276715,-4.827988955025,2,1,18
+2025-03-11T12:40:14.513916,479392817,912,204,-6.34910535468,9.68208295311,-5.99695270128,2,1,18
+2025-03-11T12:40:14.638916,479392817,912,204,-7.01743223412,11.16051519744,-7.165835529705,2,1,18
+2025-03-11T12:40:14.763916,479392817,912,204,-7.64340036768,12.638883659535,-8.293045615425,2,1,18
+2025-03-11T12:40:14.888916,479392817,912,204,-8.27878155588,14.05262891223,-9.40607505306,2,1,18
+2025-03-11T12:40:15.013916,479392817,912,204,-8.88121705284,15.443239776795,-10.4773304547,2,1,18
+2025-03-11T12:40:15.138916,479392817,912,204,-9.46482644052,16.79688664614,-11.52986996736,2,1,18
+2025-03-11T12:40:15.263916,479392817,912,204,-10.0484358282,18.11821482387,-12.54527820765,2,1,18
+2025-03-11T12:40:15.388916,479392817,912,204,-10.60851257928,19.356402360015,-13.52323656567,2,1,18
+2025-03-11T12:40:15.513916,479392817,912,204,-11.14505669376,20.566852725915,-14.459416929405,2,1,18
+2025-03-11T12:40:15.638916,479392817,912,204,-11.64394858968,21.73569379299,-15.344475500385,2,1,18
+2025-03-11T12:40:15.763916,479392817,912,204,-12.11460132168,22.82600408751,-16.1874782181,2,1,18
+2025-03-11T12:40:15.888916,479392817,912,204,-12.58525405368,23.87014482258,-16.984036428165,2,1,18
+2025-03-11T12:40:16.013916,479392817,912,204,-13.0135480398,24.840350480295,-17.747772789555,2,1,18
+2025-03-11T12:40:16.138916,479392817,912,204,-13.413602862,25.74587623329,-18.446425713855,2,1,18
+2025-03-11T12:40:16.263916,479392817,912,204,-13.7901250476,26.58672916848,-19.1123462079,2,1,18
+2025-03-11T12:40:16.388916,479392817,912,204,-14.12899501464,27.35365411323,-19.70849410488,2,1,18
+2025-03-11T12:40:16.513916,479392817,912,204,-14.43491929044,28.0512751104,-20.244144160305,2,1,18
+2025-03-11T12:40:16.638916,479392817,912,204,-14.69377829304,28.6749539433,-20.73310182828,2,1,18
+2025-03-11T12:40:16.763916,479392817,912,204,-14.94793076832,29.233988306055,-21.1524068808,2,1,18
+2025-03-11T12:40:16.888916,479392817,912,204,-15.15972449772,29.70523672362,-21.52495673235,2,1,18
+2025-03-11T12:40:17.013916,479392817,912,204,-15.32915948124,30.09331615194,-21.827675131605,2,1,18
+2025-03-11T12:40:17.138916,479392817,912,204,-15.45623571888,30.407460502905,-22.060610746065,2,1,18
+2025-03-11T12:40:17.263916,479392817,912,204,-15.55977931992,30.64308116823,-22.23302022693,2,1,18
+2025-03-11T12:40:17.388916,479392817,912,204,-15.63508375704,30.77246932533,-22.34474738397,2,1,18
+2025-03-11T12:40:17.513916,479392817,912,204,-15.66802944828,30.846390228855,-22.40064944226,2,1,18
+2025-03-11T12:40:17.638916,479392817,912,204,-15.66332292096,30.81868140627,-22.391253018,2,1,18
+2025-03-11T12:40:17.763916,479392817,912,204,-15.6256707024,30.730902547995,-22.30754706864,2,1,18
+2025-03-11T12:40:17.888916,479392817,912,204,-15.54095321064,30.573798481395,-22.16793283155,2,1,18
+2025-03-11T12:40:18.013855,479392821,908,205,-15.42799655496,30.30122799468,-21.986068071195,2,1,18
+2025-03-11T12:40:18.138855,479392821,908,205,-15.28680073536,29.954743691355,-21.697490153115,2,1,18
+2025-03-11T12:40:18.263855,479392821,908,205,-15.09853964256,29.51584939998,-21.3667426296,2,1,18
+2025-03-11T12:40:18.388855,479392821,908,205,-14.87733285852,29.016885072915,-20.97554593203,2,1,18
+2025-03-11T12:40:18.513855,479392821,908,205,-14.63259343788,28.43016314832,-20.50991408232,2,1,18
+2025-03-11T12:40:18.638855,479392821,908,205,-14.34549527136,27.783357014205,-20.0161535022,2,1,18
+2025-03-11T12:40:18.763855,479392821,908,205,-14.0254514136,27.053396064675,-19.45720196226,2,1,18
+2025-03-11T12:40:18.888855,479392821,908,205,-13.68187491924,26.26799620923,-18.85170630852,2,1,18
+2025-03-11T12:40:19.013855,479392821,908,205,-13.31476578828,25.404072668145,-18.167204053125,2,1,18
+2025-03-11T12:40:19.138855,479392821,908,205,-12.88647180216,24.466185702045,-17.44521908112,2,1,18
+2025-03-11T12:40:19.263855,479392821,908,205,-12.45817781604,23.463661352715,-16.648971564375,2,1,18
+2025-03-11T12:40:19.388855,479392821,908,205,-12.001644666,22.4103079665,-15.838534898955,2,1,18
+2025-03-11T12:40:19.513855,479392821,908,205,-11.49804624276,21.26916154818,-14.97671272782,2,1,18
+2025-03-11T12:40:19.638855,479392821,908,205,-10.98503476488,20.095682264415,-14.06387855781,2,1,18
+2025-03-11T12:40:19.763855,479392821,908,205,-10.43907759576,18.875983812795,-13.099908449025,2,1,18
+2025-03-11T12:40:19.888855,479392821,908,205,-9.88841389932,17.59164089103,-12.09862654389,2,1,18
+2025-03-11T12:40:20.013855,479392821,908,205,-9.295391457,16.265681583525,-11.087793711405,2,1,18
+2025-03-11T12:40:20.138855,479392821,908,205,-8.69295596004,14.888921586795,-10.03971189609,2,1,18
+2025-03-11T12:40:20.263855,479392821,908,205,-8.07640088112,13.498289461485,-8.936085112155,2,1,18
+2025-03-11T12:40:20.388855,479392821,908,205,-7.45043274756,12.070707514785,-7.827623165745,2,1,18
+2025-03-11T12:40:20.513855,479392821,908,205,-6.8009319774,10.60615448595,-6.681954674565,2,1,18
+2025-03-11T12:40:20.638855,479392821,908,205,-6.1420181526,9.104651635725,-5.53145102091,2,1,18
+2025-03-11T12:40:20.763855,479392821,908,205,-5.48781085512,7.5708371808,-4.34844639963,2,1,18
+2025-03-11T12:40:20.888855,479392821,908,205,-4.81948397568,6.01853364135,-3.169933997175,2,1,18
+2025-03-11T12:40:21.013855,479392821,908,205,-4.15115709624,4.47546401379,-1.97298979416,2,1,18
+2025-03-11T12:40:21.138855,479392821,908,205,-3.46400410752,2.91389821479,-0.748186803135,2,1,18
+2025-03-11T12:40:21.263855,479392821,908,205,-2.79567722808,1.366211631285,0.45802196766,2,1,18
+2025-03-11T12:40:21.388855,479392821,908,205,-2.09911118472,-0.19998529749,1.682869667895,2,1,18
+2025-03-11T12:40:21.513855,479392821,908,205,-1.40254514136,-1.775416138155,2.8985258016,2,1,18
+2025-03-11T12:40:21.638855,479392821,908,205,-0.71068562532,-3.313904244345,4.095496609515,2,1,18
+2025-03-11T12:40:21.763855,479392821,908,205,-0.03765221856,-4.84774704693,5.287782215745,2,1,18
+2025-03-11T12:40:21.888855,479392821,908,205,0.62126160624,-6.38156858877,6.452316556695,2,1,18
+2025-03-11T12:40:22.013778,479392825,903,206,1.294295013,-7.90156052352,7.6214285766,2,1,18
+2025-03-11T12:40:22.138778,479392825,903,206,1.94850231048,-9.35688672738,8.76705858801,2,1,18
+2025-03-11T12:40:22.263778,479392825,903,206,2.57447044404,-10.80293649786,9.89409833748,2,1,18
+2025-03-11T12:40:22.388778,479392825,903,206,3.18631899564,-12.230497183815,10.98404925264,2,1,18
+2025-03-11T12:40:22.513778,479392825,903,206,3.79346101992,-13.602647311515,12.041357155965,2,1,18
+2025-03-11T12:40:22.638778,479392825,903,206,4.39589651688,-14.94708861663,13.08926863503,2,1,18
+2025-03-11T12:40:22.763778,479392825,903,206,4.97479937724,-16.24532492772,14.09530478481,2,1,18
+2025-03-11T12:40:22.888778,479392825,903,206,5.530169601,-17.515824068565,15.050322706275,2,1,18
+2025-03-11T12:40:23.013778,479392825,903,206,6.05730066084,-18.7124093928,15.96792922524,2,1,18
+2025-03-11T12:40:23.138778,479392825,903,206,6.55619255676,-19.816613076645,16.85264712372,2,1,18
+2025-03-11T12:40:23.263778,479392825,903,206,7.03155181608,-20.902313502135,17.714116163475,2,1,18
+2025-03-11T12:40:23.388778,479392825,903,206,7.47867191148,-21.92795097885,18.50128586586,2,1,18
+2025-03-11T12:40:23.513778,479392825,903,206,7.89755284296,-22.879674638955,19.24642404873,2,1,18
+2025-03-11T12:40:23.638778,479392825,903,206,8.29290113784,-23.76210852531,19.931084765505,2,1,18
+2025-03-11T12:40:23.763778,479392825,903,206,8.64589068684,-24.58907515809,20.564540500545,2,1,18
+2025-03-11T12:40:23.888778,479392825,903,206,8.9659345446,-25.332886975455,21.132805275765,2,1,18
+2025-03-11T12:40:24.013778,479392825,903,206,9.26244576576,-26.021259886905,21.66838628823,2,1,18
+2025-03-11T12:40:24.138778,479392825,903,206,9.53542435032,-26.60802433299,22.138699381335,2,1,18
+2025-03-11T12:40:24.263778,479392825,903,206,9.75663113436,-27.13007343978,22.548498215715,2,1,18
+2025-03-11T12:40:24.388778,479392825,903,206,9.96842486376,-27.58747098951,22.911734831985,2,1,18
+2025-03-11T12:40:24.513778,479392825,903,206,10.12844679264,-27.961685376165,23.182019035425,2,1,18
+2025-03-11T12:40:24.638778,479392825,903,206,10.2602295576,-28.248135078375,23.387098133025,2,1,18
+2025-03-11T12:40:24.763778,479392825,903,206,10.34494704936,-28.45602566037,23.554700743455,2,1,18
+2025-03-11T12:40:24.888778,479392825,903,206,10.41083843184,-28.571548775805,23.64323393871,2,1,18
+2025-03-11T12:40:25.013778,479392825,903,206,10.4249580138,-28.603888728165,23.675775657255,2,1,18
+2025-03-11T12:40:25.138778,479392825,903,206,10.42025148648,-28.553095125855,23.629296628125,2,1,18
+2025-03-11T12:40:25.263778,479392825,903,206,10.35906663132,-28.446813009225,23.55006252213,2,1,18
+2025-03-11T12:40:25.388778,479392825,903,206,10.26493608492,-28.234291297455,23.405515787565,2,1,18
+2025-03-11T12:40:25.513778,479392825,903,206,10.1425663746,-27.957089680965,23.172785030835,2,1,18
+2025-03-11T12:40:25.638778,479392825,903,206,9.99195750036,-27.596740335975,22.893353970075,2,1,18
+2025-03-11T12:40:25.763778,479392825,903,206,9.79428335292,-27.13936404699,22.539388151025,2,1,18
+2025-03-11T12:40:25.888778,479392825,903,206,9.56837004156,-26.617307853285,22.129579128915,2,1,18
+2025-03-11T12:40:26.013717,479392829,899,207,9.32833714824,-26.03520997155,21.663981800685,2,1,18
+2025-03-11T12:40:26.138717,479392829,899,207,9.00829329048,-25.35141858147,21.14685465138,2,1,18
+2025-03-11T12:40:26.263717,479392829,899,207,8.6835429054,-24.60759967719,20.5693394544,2,1,18
+2025-03-11T12:40:26.388717,479392829,899,207,8.3070207198,-23.766746742,19.93575977946,2,1,18
+2025-03-11T12:40:26.513717,479392829,899,207,7.93520506152,-22.88434829022,19.24652988432,2,1,18
+2025-03-11T12:40:26.638717,479392829,899,207,7.52573718468,-21.94648967178,18.506105195175,2,1,18
+2025-03-11T12:40:26.763717,479392829,899,207,7.06449750732,-20.91159702243,17.714236145085,2,1,18
+2025-03-11T12:40:26.888717,479392829,899,207,6.58443172068,-19.83974037786,16.875930503925,2,1,18
+2025-03-11T12:40:27.013717,479392829,899,207,6.09024635208,-18.684757265535,15.99557523894,2,1,18
+2025-03-11T12:40:27.138717,479392829,899,207,5.54428918296,-17.474292725805,15.068614733775,2,1,18
+2025-03-11T12:40:27.263717,479392829,899,207,5.0124515958,-16.23614771115,14.09533761915,2,1,18
+2025-03-11T12:40:27.388717,479392829,899,207,4.43354873544,-14.933294444115,13.093897252635,2,1,18
+2025-03-11T12:40:27.513717,479392829,899,207,3.85464587508,-13.60273944141,12.059970064515,2,1,18
+2025-03-11T12:40:27.638717,479392829,899,207,3.2475038508,-12.235206269655,10.988826143895,2,1,18
+2025-03-11T12:40:27.763717,479392829,899,207,2.64036182652,-10.826120494395,9.88512240042,2,1,18
+2025-03-11T12:40:27.888717,479392829,899,207,2.00498063832,-9.37543959414,8.75803794174,2,1,18
+2025-03-11T12:40:28.013717,479392829,899,207,1.35077334084,-7.9016455665,7.6030703613,2,1,18
+2025-03-11T12:40:28.138717,479392829,899,207,0.69656604336,-6.38168197941,6.443239326345,2,1,18
+2025-03-11T12:40:28.263717,479392829,899,207,0.01411958196,-4.857058914885,5.2648423632,2,1,18
+2025-03-11T12:40:28.388717,479392829,899,207,-0.65420729748,-3.313989287325,4.067898160185,2,1,18
+2025-03-11T12:40:28.513717,479392829,899,207,-1.3178276496,-1.77092674668,2.875584261915,2,1,18
+2025-03-11T12:40:28.638717,479392829,899,207,-2.01439369296,-0.20934677385,1.646140778415,2,1,18
+2025-03-11T12:40:28.763717,479392829,899,207,-2.71095973632,1.347616243035,0.444442330755,2,1,18
+2025-03-11T12:40:28.888717,479392829,899,207,-3.39340619772,2.904557999175,-0.77108590476,2,1,18
+2025-03-11T12:40:29.013717,479392829,899,207,-4.07585265912,4.49381844693,-1.977544242495,2,1,18
+2025-03-11T12:40:29.138717,479392829,899,207,-4.76300564784,6.03691642215,-3.17452919643,2,1,18
+2025-03-11T12:40:29.263717,479392829,899,207,-5.44545210924,7.57539035451,-4.36685951187,2,1,18
+2025-03-11T12:40:29.388717,479392829,899,207,-6.09965940672,9.10458785349,-5.545219682385,2,1,18
+2025-03-11T12:40:29.513717,479392829,899,207,-6.76327975884,10.601480834685,-6.709569541065,2,1,18
+2025-03-11T12:40:29.638717,479392829,899,207,-7.41748705632,12.07065790638,-7.855272553725,2,1,18
+2025-03-11T12:40:29.763717,479392829,899,207,-8.05286824452,13.48902011502,-8.96832632511,2,1,18
+2025-03-11T12:40:29.888717,479392829,899,207,-8.66942332344,14.89812006411,-10.058190093,2,1,18
+2025-03-11T12:40:30.013656,479392833,895,208,-9.26715229308,16.27025601798,-11.115477620865,2,1,18
+2025-03-11T12:40:30.138656,479392833,895,208,-9.84134862612,17.61003784566,-12.149443288755,2,1,18
+2025-03-11T12:40:30.263656,479392833,895,208,-10.39201232256,18.875912943645,-13.155247975905,2,1,18
+2025-03-11T12:40:30.388656,479392833,895,208,-10.92855643704,20.10944808927,-14.096170125405,2,1,18
+2025-03-11T12:40:30.513656,479392833,895,208,-11.44627444224,21.29216837184,-15.009063150645,2,1,18
+2025-03-11T12:40:30.638656,479392833,895,208,-11.94516633816,22.41022292352,-15.866133348285,2,1,18
+2025-03-11T12:40:30.763656,479392833,895,208,-12.42052559748,23.48668943712,-16.67211231636,2,1,18
+2025-03-11T12:40:30.888656,479392833,895,208,-12.86293916556,24.498468959085,-17.45457871275,2,1,18
+2025-03-11T12:40:31.013656,479392833,895,208,-13.28182009704,25.408640015685,-18.185637540825,2,1,18
+2025-03-11T12:40:31.138656,479392833,895,208,-13.66304880996,26.27720177346,-18.847094108085,2,1,18
+2025-03-11T12:40:31.263656,479392833,895,208,-14.01133183164,27.07184262771,-19.471129085115,2,1,18
+2025-03-11T12:40:31.388656,479392833,895,208,-14.32666916208,27.811030402215,-20.02549898781,2,1,18
+2025-03-11T12:40:31.513656,479392833,895,208,-14.60906080128,28.467063361305,-20.542398632775,2,1,18
+2025-03-11T12:40:31.638656,479392833,895,208,-14.86791980388,29.053806546645,-20.9849604606,2,1,18
+2025-03-11T12:40:31.763656,479392833,895,208,-15.1079526972,29.57126704515,-21.36705501006,2,1,18
+2025-03-11T12:40:31.888656,479392833,895,208,-15.28209420804,29.968587472275,-21.716033434695,2,1,18
+2025-03-11T12:40:32.013656,479392833,895,208,-15.44211613692,30.328950991095,-21.977004402855,2,1,18
+2025-03-11T12:40:32.138656,479392833,895,208,-15.55977931992,30.60614552067,-22.172764035735,2,1,18
+2025-03-11T12:40:32.263656,479392833,895,208,-15.63979028436,30.763242500355,-22.29850773405,2,1,18
+2025-03-11T12:40:32.388656,479392833,895,208,-15.68685555756,30.864886400295,-22.39154729415,2,1,18
+2025-03-11T12:40:32.513656,479392833,895,208,-15.68685555756,30.874120312185,-22.386975844635,2,1,18
+2025-03-11T12:40:32.638656,479392833,895,208,-15.65390986632,30.80019940866,-22.33569390336,2,1,18
+2025-03-11T12:40:32.763656,479392833,895,208,-15.6021380658,30.64776190641,-22.237756367265,2,1,18
+2025-03-11T12:40:32.888656,479392833,895,208,-15.49859446476,30.402907329195,-22.05605798487,2,1,18
+2025-03-11T12:40:33.013656,479392833,895,208,-15.3668116998,30.09337284726,-21.809276165385,2,1,18
+2025-03-11T12:40:33.138656,479392833,895,208,-15.17384407968,29.70987494031,-21.4972909272,2,1,18
+2025-03-11T12:40:33.263656,479392833,895,208,-14.9667568776,29.252484477495,-21.14330473269,2,1,18
+2025-03-11T12:40:33.388656,479392833,895,208,-14.7314305116,28.70271237429,-20.72408909859,2,1,18
+2025-03-11T12:40:33.513656,479392833,895,208,-14.46786498168,28.07440949853,-20.24895726018,2,1,18
+2025-03-11T12:40:33.638656,479392833,895,208,-14.1666472332,27.358327764495,-19.68087923838,2,1,18
+2025-03-11T12:40:33.763656,479392833,895,208,-13.81836421152,26.619090381585,-19.098717319485,2,1,18
+2025-03-11T12:40:33.888656,479392833,895,208,-13.45125508056,25.787485532115,-18.46058657049,2,1,18
+2025-03-11T12:40:34.013595,479392837,891,209,-13.060613313,24.868123085115,-17.757260903385,2,1,18
+2025-03-11T12:40:34.138595,479392837,891,209,-12.62761279956,23.90252729643,-16.988918571,2,1,18
+2025-03-11T12:40:34.263595,479392837,891,209,-12.17107964952,22.84455695427,-16.173837454815,2,1,18
+2025-03-11T12:40:34.388595,479392837,891,209,-11.6957203902,21.73115479311,-15.33070288062,2,1,18
+2025-03-11T12:40:34.513595,479392837,891,209,-11.19682849428,20.571547637925,-14.42721250908,2,1,18
+2025-03-11T12:40:34.638595,479392837,891,209,-10.66969743444,19.351877533965,-13.49562397032,2,1,18
+2025-03-11T12:40:34.763595,479392837,891,209,-10.11432721068,18.095229260955,-12.51757846503,2,1,18
+2025-03-11T12:40:34.888595,479392837,891,209,-9.54954393228,16.79701421061,-11.50233264441,2,1,18
+2025-03-11T12:40:35.013595,479392837,891,209,-8.94710843532,15.452572905495,-10.44980104833,2,1,18
+2025-03-11T12:40:35.138595,479392837,891,209,-8.33525988372,14.066564823045,-9.383169721995,2,1,18
+2025-03-11T12:40:35.263595,479392837,891,209,-7.70929175016,12.638982876345,-8.2793278926,2,1,18
+2025-03-11T12:40:35.388595,479392837,891,209,-7.06920403464,11.17444402134,-7.138299893895,2,1,18
+2025-03-11T12:40:35.513595,479392837,891,209,-6.41029020984,9.68679203895,-5.974008890445,2,1,18
+2025-03-11T12:40:35.638595,479392837,891,209,-5.76078943968,8.20838814228,-4.819027163985,2,1,18
+2025-03-11T12:40:35.763595,479392837,891,209,-5.09246256024,6.660701558775,-3.617438510205,2,1,18
+2025-03-11T12:40:35.888595,479392837,891,209,-4.4006030442,5.09912867286,-2.434206384585,2,1,18
+2025-03-11T12:40:36.013595,479392837,891,209,-3.7181565828,3.55142082861,-1.23720728463,2,1,18
+2025-03-11T12:40:36.138595,479392837,891,209,-3.04041664872,2.00833702722,-0.031002472125,2,1,18
+2025-03-11T12:40:36.263595,479392837,891,209,-2.35326366,0.43753731633,1.189229069385,2,1,18
+2025-03-11T12:40:36.388595,479392837,891,209,-1.68023025324,-1.11939026598,2.400116812425,2,1,18
+2025-03-11T12:40:36.513595,479392837,891,209,-0.99778379184,-2.680948978065,3.60642914766,2,1,18
+2025-03-11T12:40:36.638595,479392837,891,209,-0.30121774848,-4.242528950895,4.79891169504,2,1,18
+2025-03-11T12:40:36.763595,479392837,891,209,0.36710913096,-5.767130754675,6.0096189141,2,1,18
+2025-03-11T12:40:36.888595,479392837,891,209,1.04014253772,-7.277888777535,7.17406214949,2,1,18
+2025-03-11T12:40:37.013595,479392837,891,209,1.6943498352,-8.7747675849,8.31991116465,2,1,18
+2025-03-11T12:40:37.138595,479392837,891,209,2.32502449608,-10.220824442295,9.460821452895,2,1,18
+2025-03-11T12:40:37.263595,479392837,891,209,2.96040568428,-11.65303751877,10.55546775747,2,1,18
+2025-03-11T12:40:37.388595,479392837,891,209,3.55813465392,-13.0621091202,11.649910891455,2,1,18
+2025-03-11T12:40:37.513595,479392837,891,209,4.17468973284,-14.40657168606,12.68861269968,2,1,18
+2025-03-11T12:40:37.638595,479392837,891,209,4.7535925932,-15.727892776875,13.7224912203,2,1,18
+2025-03-11T12:40:37.763595,479392837,891,209,5.30896281696,-16.98915800583,14.705181176355,2,1,18
+2025-03-11T12:40:37.888595,479392837,891,209,5.85491998608,-18.19962254556,15.65062214958,2,1,18
+2025-03-11T12:40:38.013534,479392841,887,210,6.3773445186,-19.36849904721,16.540351776225,2,1,18
+2025-03-11T12:40:38.138534,479392841,887,210,6.86682335988,-20.48653942506,17.397401598405,2,1,18
+2025-03-11T12:40:38.263534,479392841,887,210,7.32335650992,-21.53527585533,18.20319381306,2,1,18
+2025-03-11T12:40:38.388534,479392841,887,210,7.75165049604,-22.52856629277,18.943951258125,2,1,18
+2025-03-11T12:40:38.513534,479392841,887,210,8.13758573628,-23.43407078502,19.679534555355,2,1,18
+2025-03-11T12:40:38.638534,479392841,887,210,8.52352097652,-24.270320938095,20.340830974095,2,1,18
+2025-03-11T12:40:38.763534,479392841,887,210,8.86239094356,-25.055713706625,20.93245608906,2,1,18
+2025-03-11T12:40:38.888534,479392841,887,210,9.16360869204,-25.74409370499,21.477287523285,2,1,18
+2025-03-11T12:40:39.013534,479392841,887,210,9.43188074928,-26.390871491445,21.971007352485,2,1,18
+2025-03-11T12:40:39.138534,479392841,887,210,9.68603322456,-26.936054986365,22.399479637785,2,1,18
+2025-03-11T12:40:39.263534,479392841,887,210,9.88841389932,-27.402672274155,22.781225014155,2,1,18
+2025-03-11T12:40:39.388534,479392841,887,210,10.06726193748,-27.799999788195,23.088632573385,2,1,18
+2025-03-11T12:40:39.513534,479392841,887,210,10.2131642844,-28.109555530875,23.32620472203,2,1,18
+2025-03-11T12:40:39.638534,479392841,887,210,10.31200135812,-28.363636933065,23.517181818225,2,1,18
+2025-03-11T12:40:39.763534,479392841,887,210,10.3778927406,-28.548414387675,23.638420838835,2,1,18
+2025-03-11T12:40:39.888534,479392841,887,210,10.42966454112,-28.62236363886,23.694363648045,2,1,18
+2025-03-11T12:40:40.013534,479392841,887,210,10.43437106844,-28.61775376983,23.685109267995,2,1,18
+2025-03-11T12:40:40.138534,479392841,887,210,10.38730579524,-28.502259002055,23.61509729172,2,1,18
+2025-03-11T12:40:40.263534,479392841,887,210,10.3072948308,-28.331311154535,23.470800124095,2,1,18
+2025-03-11T12:40:40.388534,479392841,887,210,10.19433817512,-28.081825447545,23.2613363304,2,1,18
+2025-03-11T12:40:40.513534,479392841,887,210,10.04372930088,-27.74456088228,23.00974764048,2,1,18
+2025-03-11T12:40:40.638534,479392841,887,210,9.87429431736,-27.324162762345,22.688378436915,2,1,18
+2025-03-11T12:40:40.763534,479392841,887,210,9.66720711528,-26.852921431695,22.30197842205,2,1,18
+2025-03-11T12:40:40.888534,479392841,887,210,9.40834811268,-26.2707952023,21.877921396035,2,1,18
+2025-03-11T12:40:41.013534,479392841,887,210,9.11654341884,-25.647066760995,21.38889241395,2,1,18
+2025-03-11T12:40:41.138534,479392841,887,210,8.79649956108,-24.94019059119,20.82082230873,2,1,18
+2025-03-11T12:40:41.263534,479392841,887,210,8.4482165394,-24.11784800127,20.210501680245,2,1,18
+2025-03-11T12:40:41.388534,479392841,887,210,8.05757477184,-23.249272069665,19.52592415245,2,1,18
+2025-03-11T12:40:41.513534,479392841,887,210,7.65751994964,-22.320661536945,18.81790932537,2,1,18
+2025-03-11T12:40:41.638534,479392841,887,210,7.21981290888,-21.318123013785,18.049362135255,2,1,18
+2025-03-11T12:40:41.763534,479392841,887,210,6.76327975884,-20.287854407295,17.229806904555,2,1,18
+2025-03-11T12:40:41.888534,479392841,887,210,6.2832139722,-19.151360379495,16.35881977179,2,1,18
+2025-03-11T12:40:42.013473,479392845,883,211,5.77020249432,-17.964030227895,15.459772951575,2,1,18
+2025-03-11T12:40:42.138473,479392845,883,211,5.23365837984,-16.744345950105,14.50506345228,2,1,18
+2025-03-11T12:40:42.263473,479392845,883,211,4.68770121072,-15.48309489498,13.51777375467,2,1,18
+2025-03-11T12:40:42.388473,479392845,883,211,4.12762445964,-14.17565301966,12.497869337265,2,1,18
+2025-03-11T12:40:42.513473,479392845,883,211,3.5063628534,-12.80809858716,11.4405552045,2,1,18
+2025-03-11T12:40:42.638473,479392845,883,211,2.89922082912,-11.385161944065,10.346018693805,2,1,18
+2025-03-11T12:40:42.763473,479392845,883,211,2.27325269556,-9.966813909255,9.237605414895,2,1,18
+2025-03-11T12:40:42.888473,479392845,883,211,1.6237519254,-8.497643924475,8.091912589965,2,1,18
+2025-03-11T12:40:43.013473,479392845,883,211,0.9648381006,-7.000758030195,6.93219303603,2,1,18
+2025-03-11T12:40:43.138473,479392845,883,211,0.3059242758,-5.4715534443,5.7584427948,2,1,18
+2025-03-11T12:40:43.263473,479392845,883,211,-0.36240260364,-3.94695164052,4.570836160815,2,1,18
+2025-03-11T12:40:43.388473,479392845,883,211,-1.04014253772,-2.390016971295,3.38303881512,2,1,18
+2025-03-11T12:40:43.513473,479392845,883,211,-1.73200205376,-0.82844408538,2.16284575338,2,1,18
+2025-03-11T12:40:43.638473,479392845,883,211,-2.39562240588,0.73770323499,0.938069367255,2,1,18
+2025-03-11T12:40:43.763473,479392845,883,211,-3.08748192192,2.30389307685,-0.26828767719,2,1,18
+2025-03-11T12:40:43.888473,479392845,883,211,-3.77934143796,3.87008291871,-1.474644721635,2,1,18
+2025-03-11T12:40:44.013473,479392845,883,211,-4.45237484472,5.413159633185,-2.666978995365,2,1,18
+2025-03-11T12:40:44.138473,479392845,883,211,-5.12540825148,6.93776852388,-3.868456168125,2,1,18
+2025-03-11T12:40:44.263473,479392845,883,211,-5.80314818556,8.457767545545,-5.05605884382,2,1,18
+2025-03-11T12:40:44.388473,479392845,883,211,-6.46676853768,9.97312835052,-6.22974627153,2,1,18
+2025-03-11T12:40:44.513473,479392845,883,211,-7.11626930784,11.465383115025,-7.370940648195,2,1,18
+2025-03-11T12:40:44.638473,479392845,883,211,-7.75165049604,12.8975961915,-8.48406742083,2,1,18
+2025-03-11T12:40:44.763473,479392845,883,211,-8.37291210228,14.325171051285,-9.59251917951,2,1,18
+2025-03-11T12:40:44.888473,479392845,883,211,-8.98476065388,15.70656217779,-10.67298652314,2,1,18
+2025-03-11T12:40:45.013473,479392845,883,211,-9.58248962352,17.05099639599,-11.720887814475,2,1,18
+2025-03-11T12:40:45.138473,479392845,883,211,-10.15197942924,18.33998462136,-12.73147503831,2,1,18
+2025-03-11T12:40:45.263473,479392845,883,211,-10.70264312568,19.58277493962,-13.69095688656,2,1,18
+2025-03-11T12:40:45.388473,479392845,883,211,-11.25330682212,20.802480478155,-14.617976246955,2,1,18
+2025-03-11T12:40:45.513473,479392845,883,211,-11.7427856634,21.95283954762,-15.502917107475,2,1,18
+2025-03-11T12:40:45.638473,479392845,883,211,-12.2134383954,23.04314984214,-16.35516005922,2,1,18
+2025-03-11T12:40:45.763473,479392845,883,211,-12.6605584908,24.068787318855,-17.133089527575,2,1,18
+2025-03-11T12:40:45.888473,479392845,883,211,-13.07943942228,25.03897880274,-17.887565279475,2,1,18
+2025-03-11T12:40:46.013412,479392849,879,212,-13.46537466252,25.91678155932,-18.586041638085,2,1,18
+2025-03-11T12:40:46.138412,479392849,879,212,-13.83248379348,26.753003364735,-19.2149564868,2,1,18
+2025-03-11T12:40:46.263412,479392849,879,212,-14.15723417856,27.51067313685,-19.806405036075,2,1,18
+2025-03-11T12:40:46.388412,479392849,879,212,-14.47727803632,28.208315394765,-20.318985069615,2,1,18
+2025-03-11T12:40:46.513412,479392849,879,212,-14.74084356624,28.79506566702,-20.793897904275,2,1,18
+2025-03-11T12:40:46.638412,479392849,879,212,-14.97616993224,29.335603858335,-21.194584402815,2,1,18
+2025-03-11T12:40:46.763412,479392849,879,212,-15.18325713432,29.79299432115,-21.557810831355,2,1,18
+2025-03-11T12:40:46.888412,479392849,879,212,-15.33386600856,30.157960622085,-21.855746693925,2,1,18
+2025-03-11T12:40:47.013412,479392849,879,212,-15.47035530084,30.4536513231,-22.088605348845,2,1,18
+2025-03-11T12:40:47.138412,479392849,879,212,-15.5786054292,30.68004516345,-22.24249588188,2,1,18
+2025-03-11T12:40:47.263412,479392849,879,212,-15.63037722972,30.818631797865,-22.349600650755,2,1,18
+2025-03-11T12:40:47.388412,479392849,879,212,-15.65390986632,30.85560288,-22.37294684448,2,1,18
+2025-03-11T12:40:47.513412,479392849,879,212,-15.64449681168,30.814036102665,-22.349606880195,2,1,18
+2025-03-11T12:40:47.638412,479392849,879,212,-15.59743153848,30.703158290835,-22.27961923767,2,1,18
+2025-03-11T12:40:47.763412,479392849,879,212,-15.51742057404,30.51835957548,-22.135249068795,2,1,18
+2025-03-11T12:40:47.888412,479392849,879,212,-15.40446391836,30.23193822093,-21.89786990301,2,1,18
+2025-03-11T12:40:48.013412,479392849,879,212,-15.2491485168,29.88543265686,-21.623121772785,2,1,18
+2025-03-11T12:40:48.138412,479392849,879,212,-15.060887424,29.44192140954,-21.27386944746,2,1,18
+2025-03-11T12:40:48.263412,479392849,879,212,-14.83497411264,28.919865215835,-20.89178112744,2,1,18
+2025-03-11T12:40:48.388412,479392849,879,212,-14.56199552808,28.33310076975,-20.449188736425,2,1,18
+2025-03-11T12:40:48.513412,479392849,879,212,-14.2843104162,27.677074897575,-19.918438928145,2,1,18
+2025-03-11T12:40:48.638412,479392849,879,212,-13.95956003112,26.93787294924,-19.350188298945,2,1,18
+2025-03-11T12:40:48.763412,479392849,879,212,-13.59245090016,26.12473592355,-18.726015235995,2,1,18
+2025-03-11T12:40:48.888412,479392849,879,212,-13.19710260528,25.223834213415,-18.04125718422,2,1,18
+2025-03-11T12:40:49.013412,479392849,879,212,-12.78763472844,24.27212472714,-17.291519259795,2,1,18
+2025-03-11T12:40:49.138412,479392849,879,212,-12.33580810572,23.260331031345,-16.4951721369,2,1,18
+2025-03-11T12:40:49.263412,479392849,879,212,-11.883981483,22.2023677761,-15.6662408574,2,1,18
+2025-03-11T12:40:49.388412,479392849,879,212,-11.38508958708,21.07507931253,-14.786021407185,2,1,18
+2025-03-11T12:40:49.513412,479392849,879,212,-10.86266505456,19.883118031155,-13.873069526715,2,1,18
+2025-03-11T12:40:49.638412,479392849,879,212,-10.32141441276,18.631107974835,-12.913559386425,2,1,18
+2025-03-11T12:40:49.763412,479392849,879,212,-9.74721807972,17.328261794715,-11.89364873958,2,1,18
+2025-03-11T12:40:49.888412,479392849,879,212,-9.17302174668,15.99309692298,-10.86894763947,2,1,18
+2025-03-11T12:40:50.013336,479392853,874,213,-8.5658797224,14.62094679528,-9.80701961913,2,1,18
+2025-03-11T12:40:50.138336,479392853,874,213,-7.93991158884,13.207215716415,-8.707870908,2,1,18
+2025-03-11T12:40:50.263336,479392853,874,213,-7.31394345528,11.770399857825,-7.594740177075,2,1,18
+2025-03-11T12:40:50.388336,479392853,874,213,-6.66914921244,10.278152180235,-6.44431575411,2,1,18
+2025-03-11T12:40:50.513336,479392853,874,213,-6.01494191496,8.785890328815,-5.284630721655,2,1,18
+2025-03-11T12:40:50.638336,479392853,874,213,-5.33249545356,7.26126726429,-4.11547399254,2,1,18
+2025-03-11T12:40:50.763336,479392853,874,213,-4.65004899216,5.727410287875,-2.93240824488,2,1,18
+2025-03-11T12:40:50.888336,479392853,874,213,-3.9770155854,4.16586574962,-1.73073640212,2,1,18
+2025-03-11T12:40:51.013336,479392853,874,213,-3.29927565132,2.60431412445,-0.505953786555,2,1,18
+2025-03-11T12:40:51.138336,479392853,874,213,-2.60741613528,1.04735819448,0.70035459039,2,1,18
+2025-03-11T12:40:51.263336,479392853,874,213,-1.92496967388,-0.514200517605,1.915907159655,2,1,18
+2025-03-11T12:40:51.388336,479392853,874,213,-1.25193626712,-2.07574505586,3.136059470475,2,1,18
+2025-03-11T12:40:51.513336,479392853,874,213,-0.56007675108,-3.637317941775,4.33315194714,2,1,18
+2025-03-11T12:40:51.638336,479392853,874,213,0.11295665568,-5.166543788415,5.530033336635,2,1,18
+2025-03-11T12:40:51.763336,479392853,874,213,0.7765770078,-6.70037241717,6.69919798233,2,1,18
+2025-03-11T12:40:51.888336,479392853,874,213,1.44019735992,-8.19264844242,7.86352350726,2,1,18
+2025-03-11T12:40:52.013336,479392853,874,213,2.08969813008,-9.65258451531,9.01840789872,2,1,18
+2025-03-11T12:40:52.138336,479392853,874,213,2.71566626364,-11.103251241735,10.12699151388,2,1,18
+2025-03-11T12:40:52.263336,479392853,874,213,3.35104745184,-12.51699649443,11.21692036644,2,1,18
+2025-03-11T12:40:52.388336,479392853,874,213,3.9534829488,-13.87528866738,12.26952496377,2,1,18
+2025-03-11T12:40:52.513336,479392853,874,213,4.52767928184,-15.219687451005,13.29427473138,2,1,18
+2025-03-11T12:40:52.638336,479392853,874,213,5.10187561488,-16.494831895455,14.304799141695,2,1,18
+2025-03-11T12:40:52.763336,479392853,874,213,5.65253931132,-17.73300525777,15.255016422165,2,1,18
+2025-03-11T12:40:52.888336,479392853,874,213,6.16084426188,-18.911094410565,16.167864738195,2,1,18
+2025-03-11T12:40:53.013336,479392853,874,213,6.66444268512,-20.06609169672,17.05748061267,2,1,18
+2025-03-11T12:40:53.138336,479392853,874,213,7.1539215264,-21.11026077945,17.88642039276,2,1,18
+2025-03-11T12:40:53.263336,479392853,874,213,7.58692203984,-22.131260039475,18.66891508119,2,1,18
+2025-03-11T12:40:53.388336,479392853,874,213,7.99638991668,-23.087586481695,19.37709628623,2,1,18
+2025-03-11T12:40:53.513336,479392853,874,213,8.39644473888,-23.95617658713,20.070934423515,2,1,18
+2025-03-11T12:40:53.638336,479392853,874,213,8.74002123324,-24.741576442575,20.694910545315,2,1,18
+2025-03-11T12:40:53.763336,479392853,874,213,9.06947814564,-25.480785477825,21.26779147926,2,1,18
+2025-03-11T12:40:53.888336,479392853,874,213,9.3659893668,-26.13683969766,21.77086133637,2,1,18
+2025-03-11T12:40:54.013275,479392857,870,214,9.6248483694,-26.73281679489,22.231952299755,2,1,18
+2025-03-11T12:40:54.138275,479392857,870,214,9.84134862612,-27.25947577071,22.614044578065,2,1,18
+2025-03-11T12:40:54.263275,479392857,870,214,10.0484358282,-27.698398409745,22.958693203545,2,1,18
+2025-03-11T12:40:54.388275,479392857,870,214,10.20845775708,-28.040294104785,23.21494671969,2,1,18
+2025-03-11T12:40:54.513275,479392857,870,214,10.32141441276,-28.3128645915,23.424532182135,2,1,18
+2025-03-11T12:40:54.638275,479392857,870,214,10.39671884988,-28.483805352105,23.582679513075,2,1,18
+2025-03-11T12:40:54.763275,479392857,870,214,10.45319717772,-28.59008038182,23.675763782385,2,1,18
+2025-03-11T12:40:54.888275,479392857,870,214,10.47672981432,-28.627051463955,23.69910997611,2,1,18
+2025-03-11T12:40:55.013275,479392857,870,214,10.43437106844,-28.557733342545,23.65245211014,2,1,18
+2025-03-11T12:40:55.138275,479392857,870,214,10.36377315864,-28.41911836047,23.54068647333,2,1,18
+2025-03-11T12:40:55.263275,479392857,870,214,10.29317524884,-28.21124903922,23.36387419206,2,1,18
+2025-03-11T12:40:55.388275,479392857,870,214,10.15668595656,-27.90170747037,23.11246206783,2,1,18
+2025-03-11T12:40:55.513275,479392857,870,214,9.98725097304,-27.49516021827,22.828126801635,2,1,18
+2025-03-11T12:40:55.638275,479392857,870,214,9.78487029828,-27.060861622095,22.46965234659,2,1,18
+2025-03-11T12:40:55.763275,479392857,870,214,9.54954393228,-26.52032343078,22.05972561402,2,1,18
+2025-03-11T12:40:55.888275,479392857,870,214,9.27656534772,-25.90124029308,21.59386230168,2,1,18
+2025-03-11T12:40:56.013275,479392857,870,214,8.9659345446,-25.194378297105,21.048913156995,2,1,18
+2025-03-11T12:40:56.138275,479392857,870,214,8.63177110488,-24.42746043927,20.462015681775,2,1,18
+2025-03-11T12:40:56.263275,479392857,870,214,8.26466197392,-23.600472545745,19.80542879847,2,1,18
+2025-03-11T12:40:56.388275,479392857,870,214,7.8599006244,-22.69955666178,19.11603025422,2,1,18
+2025-03-11T12:40:56.513275,479392857,870,214,7.45513927488,-21.73862035053,18.36163373301,2,1,18
+2025-03-11T12:40:56.638275,479392857,870,214,6.99860612484,-20.694500876205,17.56048596912,2,1,18
+2025-03-11T12:40:56.763275,479392857,870,214,6.52324686552,-19.618034362605,16.699065596865,2,1,18
+2025-03-11T12:40:56.888275,479392857,870,214,6.0243549696,-18.4768950312,15.823393262415,2,1,18
+2025-03-11T12:40:57.013275,479392857,870,214,5.48781085512,-17.2664446653,14.87797266465,2,1,18
+2025-03-11T12:40:57.138275,479392857,870,214,4.92773410404,-16.009789305375,13.904537088645,2,1,18
+2025-03-11T12:40:57.263275,479392857,870,214,4.353537771,-14.706943125255,12.89386667583,2,1,18
+2025-03-11T12:40:57.388275,479392857,870,214,3.76992838332,-13.357913211855,11.855211847965,2,1,18
+2025-03-11T12:40:57.513275,479392857,870,214,3.18161246832,-11.985791431815,10.784084344515,2,1,18
+2025-03-11T12:40:57.638275,479392857,870,214,2.56035086208,-10.562833527975,9.675656919585,2,1,18
+2025-03-11T12:40:57.763275,479392857,870,214,1.92496967388,-9.107535671775,8.5624084782,2,1,18
+2025-03-11T12:40:57.888275,479392857,870,214,1.25664279444,-7.61525255961,7.40731299957,2,1,18
+2025-03-11T12:40:58.013214,479392861,866,215,0.59302244232,-6.109125666525,6.2151937713,2,1,18
+2025-03-11T12:40:58.138214,479392861,866,215,-0.0705979098,-4.570680081825,5.027524323795,2,1,18
+2025-03-11T12:40:58.263214,479392861,866,215,-0.74363131656,-3.013752499515,3.853597516875,2,1,18
+2025-03-11T12:40:58.388214,479392861,866,215,-1.44019735992,-1.47525730641,2.661236638245,2,1,18
+2025-03-11T12:40:58.513214,479392861,866,215,-2.12735034864,0.0770745807,1.450342665765,2,1,18
+2025-03-11T12:40:58.638214,479392861,866,215,-2.80979681004,1.64325024873,0.239385879765,2,1,18
+2025-03-11T12:40:58.763214,479392861,866,215,-3.49224327144,3.195575048925,-0.99459849006,2,1,18
+2025-03-11T12:40:58.888214,479392861,866,215,-4.19351584212,4.77562993245,-2.20566902823,2,1,18
+2025-03-11T12:40:59.013214,479392861,866,215,-4.86654924888,6.309472735035,-3.40719486849,2,1,18
+2025-03-11T12:40:59.138214,479392861,866,215,-5.54428918296,7.84793958048,-4.585654645155,2,1,18
+2025-03-11T12:40:59.263214,479392861,866,215,-6.22202911704,9.358704690255,-5.74548795126,2,1,18
+2025-03-11T12:40:59.388214,479392861,866,215,-6.86211683256,10.85094528093,-6.89128206948,2,1,18
+2025-03-11T12:40:59.513214,479392861,866,215,-7.50220454808,12.31086717999,-8.023045500405,2,1,18
+2025-03-11T12:40:59.638214,479392861,866,215,-8.13287920896,13.756924037385,-9.13623508656,2,1,18
+2025-03-11T12:40:59.763214,479392861,866,215,-8.74002123324,15.1613928567,-10.21681391121,2,1,18
+2025-03-11T12:40:59.888214,479392861,866,215,-9.34716325752,16.510458204675,-11.274000145785,2,1,18
+2025-03-11T12:41:00.013214,479392861,866,215,-9.9072400086,17.827133991885,-12.30319346472,2,1,18
+2025-03-11T12:41:00.138214,479392861,866,215,-10.472023287,19.09764730656,-13.276712229705,2,1,18
+2025-03-11T12:41:00.263214,479392861,866,215,-11.02268698344,20.326586756985,-14.22226072566,2,1,18
+2025-03-11T12:41:00.388214,479392861,866,215,-11.51687235204,21.4908037812,-15.15348594531,2,1,18
+2025-03-11T12:41:00.513214,479392861,866,215,-12.01105772064,22.599617334075,-16.00125705369,2,1,18
+2025-03-11T12:41:00.638214,479392861,866,215,-12.46759087068,23.6437368084,-16.807024934595,2,1,18
+2025-03-11T12:41:00.763214,479392861,866,215,-12.91471096608,24.6370555935,-17.598644417745,2,1,18
+2025-03-11T12:41:00.888214,479392861,866,215,-13.33829842488,25.58878634052,-18.316072086255,2,1,18
+2025-03-11T12:41:01.013214,479392861,866,215,-13.70540755584,26.42039118999,-18.98192353734,2,1,18
+2025-03-11T12:41:01.138214,479392861,866,215,-14.0489840502,27.205791045435,-19.582799074065,2,1,18
+2025-03-11T12:41:01.263214,479392861,866,215,-14.35961485332,27.93112086519,-20.132465670765,2,1,18
+2025-03-11T12:41:01.388214,479392861,866,215,-14.64200649252,28.564069044555,-20.626143061905,2,1,18
+2025-03-11T12:41:01.513214,479392861,866,215,-14.89145244048,29.11847936445,-21.063894061005,2,1,18
+2025-03-11T12:41:01.638214,479392861,866,215,-15.1079526972,29.58973486893,-21.4410742173,2,1,18
+2025-03-11T12:41:01.763214,479392861,866,215,-15.29150726268,30.024005117445,-21.762546985305,2,1,18
+2025-03-11T12:41:01.888214,479392861,866,215,-15.44682266424,30.352042857735,-22.00023684441,2,1,18
+2025-03-11T12:41:02.013153,479392865,862,216,-15.56919237456,30.601542738555,-22.19586066252,2,1,18
+2025-03-11T12:41:02.138153,479392865,862,216,-15.63979028436,30.781710324135,-22.330945888155,2,1,18
+2025-03-11T12:41:02.263153,479392865,862,216,-15.67744250292,30.86025527052,-22.396122701955,2,1,18
+2025-03-11T12:41:02.388153,479392865,862,216,-15.649203339,30.84174492525,-22.39134412356,2,1,18
+2025-03-11T12:41:02.513153,479392865,862,216,-15.62096417508,30.74936328486,-22.335354918,2,1,18
+2025-03-11T12:41:02.638153,479392865,862,216,-15.55977931992,30.583060740945,-22.20498318609,2,1,18
+2025-03-11T12:41:02.763153,479392865,862,216,-15.4609422462,30.347447162535,-22.014103424895,2,1,18
+2025-03-11T12:41:02.888153,479392865,862,216,-15.32915948124,30.024061812765,-21.762628487145,2,1,18
+2025-03-11T12:41:03.013153,479392865,862,216,-15.15972449772,29.626748472555,-21.446001069345,2,1,18
+2025-03-11T12:41:03.138153,479392865,862,216,-14.943224241,29.127791232405,-21.06867491055,2,1,18
+2025-03-11T12:41:03.263153,479392865,862,216,-14.69377829304,28.55491308873,-20.644686927495,2,1,18
+2025-03-11T12:41:03.388153,479392865,862,216,-14.41138665384,27.9358157772,-20.151082537605,2,1,18
+2025-03-11T12:41:03.513153,479392865,862,216,-14.10546237804,27.233577824085,-19.58768744634,2,1,18
+2025-03-11T12:41:03.638153,479392865,862,216,-13.766592411,26.438951143665,-18.986773429845,2,1,18
+2025-03-11T12:41:03.763153,479392865,862,216,-13.38536369808,25.584240253725,-18.325389863835,2,1,18
+2025-03-11T12:41:03.888153,479392865,862,216,-12.98530887588,24.664863632895,-17.617423704255,2,1,18
+2025-03-11T12:41:04.013153,479392865,862,216,-12.55701488976,23.6761901514,-16.85821012488,2,1,18
+2025-03-11T12:41:04.138153,479392865,862,216,-12.08636215776,22.627432460385,-16.02928676196,2,1,18
+2025-03-11T12:41:04.263153,479392865,862,216,-11.59217678916,21.51861890751,-15.16303518552,2,1,18
+2025-03-11T12:41:04.388153,479392865,862,216,-11.07916531128,20.354373535635,-14.26873015107,2,1,18
+2025-03-11T12:41:04.513153,479392865,862,216,-10.55203425144,19.134703431675,-13.332521495295,2,1,18
+2025-03-11T12:41:04.638153,479392865,862,216,-9.99666402768,17.88267211461,-12.354500323755,2,1,18
+2025-03-11T12:41:04.763153,479392865,862,216,-9.41305464,16.547493069045,-11.320538614155,2,1,18
+2025-03-11T12:41:04.888153,479392865,862,216,-8.824738725,15.175371289005,-10.26327146175,2,1,18
+2025-03-11T12:41:05.013153,479392865,862,216,-8.20818364608,13.78935611964,-9.18276959664,2,1,18
+2025-03-11T12:41:05.138153,479392865,862,216,-7.56338940324,12.347894957445,-8.07419389806,2,1,18
+2025-03-11T12:41:05.263153,479392865,862,216,-6.9185951604,10.88796597147,-6.960900747465,2,1,18
+2025-03-11T12:41:05.388153,479392865,862,216,-6.26438786292,9.39570412005,-5.80121571501,2,1,18
+2025-03-11T12:41:05.513153,479392865,862,216,-5.6243001474,7.87114483776,-4.62753055845,2,1,18
+2025-03-11T12:41:05.638153,479392865,862,216,-4.95597326796,6.35577694587,-3.430732357935,2,1,18
+2025-03-11T12:41:05.763153,479392865,862,216,-4.2829398612,4.821934143285,-2.229206517675,2,1,18
+2025-03-11T12:41:05.888153,479392865,862,216,-3.59108034516,3.25112734548,-1.036685490525,2,1,18
+2025-03-11T12:41:06.013077,479392869,857,217,-2.90392735644,1.68032763459,0.188166168,2,1,18
+2025-03-11T12:41:06.138077,479392869,857,217,-2.22148089504,0.14185370223,1.3989769515,2,1,18
+2025-03-11T12:41:06.263077,479392869,857,217,-1.54374096096,-1.41969792294,2.605279099005,2,1,18
+2025-03-11T12:41:06.388077,479392869,857,217,-0.8471749176,-2.967427027935,3.82078923021,2,1,18
+2025-03-11T12:41:06.513077,479392869,857,217,-0.16002192888,-4.50590804721,5.017749850395,2,1,18
+2025-03-11T12:41:06.638077,479392869,857,217,0.53183758716,-6.0443961534,6.219340775325,2,1,18
+2025-03-11T12:41:06.763077,479392869,857,217,1.20487099392,-7.559771132205,7.411529046555,2,1,18
+2025-03-11T12:41:06.888077,479392869,857,217,1.84025218212,-9.03815376813,8.538759507735,2,1,18
+2025-03-11T12:41:07.013077,479392869,857,217,2.47563337032,-10.488834668385,9.65198361537,2,1,18
+2025-03-11T12:41:07.138077,479392869,857,217,3.09689497656,-11.911792572225,10.755790923285,2,1,18
+2025-03-11T12:41:07.263077,479392869,857,217,3.69933047352,-13.31163734868,11.82247487541,2,1,18
+2025-03-11T12:41:07.388077,479392869,857,217,4.29705944316,-14.660688522825,12.861160266465,2,1,18
+2025-03-11T12:41:07.513077,479392869,857,217,4.86654924888,-15.96352761603,13.88106072558,2,1,18
+2025-03-11T12:41:07.638077,479392869,857,217,5.42191947264,-17.234026756875,14.86841946615,2,1,18
+2025-03-11T12:41:07.763077,479392869,857,217,5.9537570598,-18.44447003586,15.804589642155,2,1,18
+2025-03-11T12:41:07.888077,479392869,857,217,6.46676853768,-19.599481495845,16.70346612612,2,1,18
+2025-03-11T12:41:08.013077,479392869,857,217,6.94683432432,-20.69442292014,17.54189343603,2,1,18
+2025-03-11T12:41:08.138077,479392869,857,217,7.40336747436,-21.720074570685,18.347563981935,2,1,18
+2025-03-11T12:41:08.263077,479392869,857,217,7.81754187852,-22.67640809982,19.09733642784,2,1,18
+2025-03-11T12:41:08.388077,479392869,857,217,8.22230322804,-23.56347311595,19.81438267293,2,1,18
+2025-03-11T12:41:08.513077,479392869,857,217,8.589412359,-24.42277970109,20.452659424425,2,1,18
+2025-03-11T12:41:08.638077,479392869,857,217,8.93769538068,-25.19895273156,21.05349648138,2,1,18
+2025-03-11T12:41:08.763077,479392869,857,217,9.25303271112,-25.891970946615,21.579902344485,2,1,18
+2025-03-11T12:41:08.888077,479392869,857,217,9.52130476836,-26.524897865235,22.073549172435,2,1,18
+2025-03-11T12:41:09.013077,479392869,857,217,9.75663113436,-27.070053012495,22.48812035577,2,1,18
+2025-03-11T12:41:09.138077,479392869,857,217,9.9778379184,-27.518230824165,22.82360797791,2,1,18
+2025-03-11T12:41:09.263077,479392869,857,217,10.14727290192,-27.906310252485,23.117086143135,2,1,18
+2025-03-11T12:41:09.388077,479392869,857,217,10.27434913956,-28.206603735615,23.368429224405,2,1,18
+2025-03-11T12:41:09.513077,479392869,857,217,10.38259926792,-28.423763664075,23.540751558,2,1,18
+2025-03-11T12:41:09.638077,479392869,857,217,10.4484906504,-28.580839383015,23.64336410805,2,1,18
+2025-03-11T12:41:09.763077,479392869,857,217,10.472023287,-28.60857655326,23.685142102335,2,1,18
+2025-03-11T12:41:09.888077,479392869,857,217,10.45319717772,-28.585463425875,23.66187909759,2,1,18
+2025-03-11T12:41:10.013015,479392873,853,218,10.41554495916,-28.483833699765,23.582720263995,2,1,18
+2025-03-11T12:41:10.138015,479392873,853,218,10.31670788544,-28.294389680805,23.44752524448,2,1,18
+2025-03-11T12:41:10.263015,479392873,853,218,10.19433817512,-28.035655888095,23.228752173795,2,1,18
+2025-03-11T12:41:10.388015,479392873,853,218,10.03902277356,-27.69376727997,22.95402837732,2,1,18
+2025-03-11T12:41:10.513015,479392873,853,218,9.85076168076,-27.264106900485,22.614089287275,2,1,18
+2025-03-11T12:41:10.638015,479392873,853,218,9.63896795136,-26.72822109969,22.21809817815,2,1,18
+2025-03-11T12:41:10.763015,479392873,853,218,9.38481547608,-26.159952825045,21.766403639025,2,1,18
+2025-03-11T12:41:10.888015,479392873,853,218,9.11654341884,-25.5039411267,21.263394908295,2,1,18
+2025-03-11T12:41:11.013015,479392873,853,218,8.78237997912,-24.76934196048,20.6997683544,2,1,18
+2025-03-11T12:41:11.138015,479392873,853,218,8.42939043012,-23.95160923959,20.089461871935,2,1,18
+2025-03-11T12:41:11.263015,479392873,853,218,8.0481617172,-23.092281393705,19.41419362113,2,1,18
+2025-03-11T12:41:11.388015,479392873,853,218,7.648106895,-22.14981999315,18.66914485668,2,1,18
+2025-03-11T12:41:11.513015,479392873,853,218,7.20569332692,-21.14265742713,17.891322911055,2,1,18
+2025-03-11T12:41:11.638015,479392873,853,218,6.73504059492,-20.05234713261,17.05756042737,2,1,18
+2025-03-11T12:41:11.763015,479392873,853,218,6.24085522632,-18.9296827119,16.177375498635,2,1,18
+2025-03-11T12:41:11.888015,479392873,853,218,5.72313722112,-17.75619634122,15.25991102388,2,1,18
+2025-03-11T12:41:12.013015,479392873,853,218,5.17247352468,-16.51340602296,14.30966940966,2,1,18
+2025-03-11T12:41:12.138015,479392873,853,218,4.60298371896,-15.229034753535,13.317586987635,2,1,18
+2025-03-11T12:41:12.263015,479392873,853,218,4.01937433128,-13.91232353175,12.28834273005,2,1,18
+2025-03-11T12:41:12.388015,479392873,853,218,3.42164536164,-12.54018757788,11.2356753192,2,1,18
+2025-03-11T12:41:12.513015,479392873,853,218,2.8003837554,-11.131080541875,10.141181246565,2,1,18
+2025-03-11T12:41:12.638015,479392873,853,218,2.16029603988,-9.689626466595,9.014135267655,2,1,18
+2025-03-11T12:41:12.763015,479392873,853,218,1.53432790632,-8.225108872335,7.87313783214,2,1,18
+2025-03-11T12:41:12.888015,479392873,853,218,0.88953366348,-6.723627282855,6.704184273615,2,1,18
+2025-03-11T12:41:13.013015,479392873,853,218,0.21650025672,-5.20825230405,5.530476470445,2,1,18
+2025-03-11T12:41:13.138015,479392873,853,218,-0.470652732,-3.67438824072,4.33354018401,2,1,18
+2025-03-11T12:41:13.263015,479392873,853,218,-1.1530991934,-2.12668039647,3.145781318085,2,1,18
+2025-03-11T12:41:13.388015,479392873,853,218,-1.84495870944,-0.56049055461,1.925563922595,2,1,18
+2025-03-11T12:41:13.513015,479392873,853,218,-2.52740517084,1.00568511342,0.714607136595,2,1,18
+2025-03-11T12:41:13.638015,479392873,853,218,-3.21926468688,2.567257999335,-0.496345691115,2,1,18
+2025-03-11T12:41:13.763015,479392873,853,218,-3.91112420292,4.142681753085,-1.707371520075,2,1,18
+2025-03-11T12:41:13.888015,479392873,853,218,-4.588864137,5.69038251042,-2.9043604323,2,1,18
+2025-03-11T12:41:14.012954,479392877,849,219,-5.26189754376,7.22884226895,-4.101290489295,2,1,18
+2025-03-11T12:41:14.137954,479392877,849,219,-5.93493095052,8.762685071535,-5.275095627465,2,1,18
+2025-03-11T12:41:14.262954,479392877,849,219,-6.59384477532,10.259570965815,-6.44405541543,2,1,18
+2025-03-11T12:41:14.387954,479392877,849,219,-7.2480520728,11.724131081565,-7.57125362628,2,1,18
+2025-03-11T12:41:14.512954,479392877,849,219,-7.87872673368,13.17942185085,-8.69835223098,2,1,18
+2025-03-11T12:41:14.637954,479392877,849,219,-8.48116223064,14.58388358325,-9.79740133596,2,1,18
+2025-03-11T12:41:14.762954,479392877,849,219,-9.09771730956,15.951430928835,-10.86856563204,2,1,18
+2025-03-11T12:41:14.887954,479392877,849,219,-9.69073975188,17.30509197201,-11.907265169115,2,1,18
+2025-03-11T12:41:15.012954,479392877,849,219,-10.25081650296,18.589449067605,-12.903947332695,2,1,18
+2025-03-11T12:41:15.137954,479392877,849,219,-10.8014801994,19.81838851803,-13.854115945665,2,1,18
+2025-03-11T12:41:15.262954,479392877,849,219,-11.3191982046,21.005725756545,-14.785513772715,2,1,18
+2025-03-11T12:41:15.387954,479392877,849,219,-11.80397051856,22.13299295937,-15.67494289377,2,1,18
+2025-03-11T12:41:15.512954,479392877,849,219,-12.28874283252,23.223324514635,-16.499495706615,2,1,18
+2025-03-11T12:41:15.637954,479392877,849,219,-12.73586292792,24.253578947295,-17.27744950872,2,1,18
+2025-03-11T12:41:15.762954,479392877,849,219,-13.1547438594,25.172983915785,-18.017797238325,2,1,18
+2025-03-11T12:41:15.887954,479392877,849,219,-13.55009215428,26.041566934305,-18.697764836835,2,1,18
+2025-03-11T12:41:16.012954,479392877,849,219,-13.88896212132,26.863895350395,-19.331165674935,2,1,18
+2025-03-11T12:41:16.137954,479392877,849,219,-14.21841903372,27.603104385645,-19.89480637485,2,1,18
+2025-03-11T12:41:16.262954,479392877,849,219,-14.52904983684,28.27303073406,-20.41646026446,2,1,18
+2025-03-11T12:41:16.387954,479392877,849,219,-14.79732189408,28.892106784845,-20.877693272055,2,1,18
+2025-03-11T12:41:16.512954,479392877,849,219,-15.02323520544,29.41416297855,-21.287502294165,2,1,18
+2025-03-11T12:41:16.637954,479392877,849,219,-15.2256158802,29.848461574725,-21.61825604712,2,1,18
+2025-03-11T12:41:16.762954,479392877,849,219,-15.3903443364,30.21806609235,-21.893146221555,2,1,18
+2025-03-11T12:41:16.887954,479392877,849,219,-15.51742057404,30.495274795755,-22.10278658094,2,1,18
+2025-03-11T12:41:17.012954,479392877,849,219,-15.59272501116,30.680066424195,-22.256386796115,2,1,18
+2025-03-11T12:41:17.137954,479392877,849,219,-15.64449681168,30.795568278885,-22.349509545195,2,1,18
+2025-03-11T12:41:17.262954,479392877,849,219,-15.65861639364,30.827908231245,-22.395911614785,2,1,18
+2025-03-11T12:41:17.387954,479392877,849,219,-15.63508375704,30.786320193165,-22.35406061925,2,1,18
+2025-03-11T12:41:17.512954,479392877,849,219,-15.58331195652,30.661584426585,-22.25164896864,2,1,18
+2025-03-11T12:41:17.637954,479392877,849,219,-15.50330099208,30.453700931505,-22.07481631191,2,1,18
+2025-03-11T12:41:17.762954,479392877,849,219,-15.3668116998,30.16724414238,-21.865106909565,2,1,18
+2025-03-11T12:41:17.887954,479392877,849,219,-15.20678977092,29.77917888789,-21.5716491198,2,1,18
+2025-03-11T12:41:18.012893,479392881,845,220,-15.00440909616,29.33102942388,-21.22696201455,2,1,18
+2025-03-11T12:41:18.137893,479392881,845,220,-14.76437620284,28.795101101595,-20.812429310985,2,1,18
+2025-03-11T12:41:18.262893,479392881,845,220,-14.4961041456,28.20372678648,-20.36058253992,2,1,18
+2025-03-11T12:41:18.387893,479392881,845,220,-14.19959292444,27.52458778692,-19.815809960925,2,1,18
+2025-03-11T12:41:18.512893,479392881,845,220,-13.884255594,26.757698276745,-19.219713002595,2,1,18
+2025-03-11T12:41:18.637893,479392881,845,220,-13.51243993572,25.94455416414,-18.595529751915,2,1,18
+2025-03-11T12:41:18.762893,479392881,845,220,-13.11709164084,25.052886365895,-17.91082036764,2,1,18
+2025-03-11T12:41:18.887893,479392881,845,220,-12.67938460008,24.059581754625,-17.160802313085,2,1,18
+2025-03-11T12:41:19.012893,479392881,845,220,-12.24638408664,23.024731626765,-16.350513921315,2,1,18
+2025-03-11T12:41:19.137893,479392881,845,220,-11.77573135464,21.934421332245,-15.512131320615,2,1,18
+2025-03-11T12:41:19.262893,479392881,845,220,-11.28154598604,20.7979060437,-14.627253273615,2,1,18
+2025-03-11T12:41:19.387893,479392881,845,220,-10.75912145352,19.59209389449,-13.704988157865,2,1,18
+2025-03-11T12:41:19.512893,479392881,845,220,-10.21787081172,18.35855166195,-12.73171500153,2,1,18
+2025-03-11T12:41:19.637893,479392881,845,220,-9.64367447868,17.069556349665,-11.721117589965,2,1,18
+2025-03-11T12:41:19.762893,479392881,845,220,-9.04594550904,15.7389729993,-10.70101000197,2,1,18
+2025-03-11T12:41:19.887893,479392881,845,220,-8.43409695744,14.34373100496,-9.61122942306,2,1,18
+2025-03-11T12:41:20.012893,479392881,845,220,-7.80812882388,12.920766014205,-8.5027918104,2,1,18
+2025-03-11T12:41:20.137893,479392881,845,220,-7.18216069032,11.474716243725,-7.38499229496,2,1,18
+2025-03-11T12:41:20.262893,479392881,845,220,-6.52324686552,10.005532085115,-6.2485193286,2,1,18
+2025-03-11T12:41:20.387893,479392881,845,220,-5.8596265134,8.50863910392,-5.07492923589,2,1,18
+2025-03-11T12:41:20.512893,479392881,845,220,-5.18659310664,6.956328477555,-3.896406645705,2,1,18
+2025-03-11T12:41:20.637893,479392881,845,220,-4.5182662272,5.413258849995,-2.713322793735,2,1,18
+2025-03-11T12:41:20.762893,479392881,845,220,-3.84993934776,3.870189222435,-1.502518239675,2,1,18
+2025-03-11T12:41:20.887893,479392881,845,220,-3.16278635904,2.30400646749,-0.29617138296,2,1,18
+2025-03-11T12:41:21.012893,479392881,845,220,-2.470926843,0.751667493465,0.91473277725,2,1,18
+2025-03-11T12:41:21.137893,479392881,845,220,-1.78377385428,-0.809898305535,2.130295534245,2,1,18
+2025-03-11T12:41:21.262893,479392881,845,220,-1.11074044752,-2.376059799735,3.32737159374,2,1,18
+2025-03-11T12:41:21.387893,479392881,845,220,-0.43300051344,-3.919143601125,4.52895628923,2,1,18
+2025-03-11T12:41:21.512893,479392881,845,220,0.25415247528,-5.443773752565,5.73046402518,2,1,18
+2025-03-11T12:41:21.637893,479392881,845,220,0.89894671812,-6.94987229799,6.90406203447,2,1,18
+2025-03-11T12:41:21.762893,479392881,845,220,1.56256707024,-8.45138223513,8.04995575884,2,1,18
+2025-03-11T12:41:21.887893,479392881,845,220,2.20265478576,-9.915921090135,9.181743523515,2,1,18
+2025-03-11T12:41:22.012832,479392885,841,221,2.85215555592,-11.38047411897,10.318171780665,2,1,18
+2025-03-11T12:41:22.137832,479392885,841,221,3.44988452556,-12.766460940675,11.417113362915,2,1,18
+2025-03-11T12:41:22.262832,479392885,841,221,4.04290696788,-14.124738939795,12.460457350755,2,1,18
+2025-03-11T12:41:22.387832,479392885,841,221,4.62180982824,-15.441443074665,13.47121095255,2,1,18
+2025-03-11T12:41:22.512832,479392885,841,221,5.20541921592,-16.725835604835,14.45870382075,2,1,18
+2025-03-11T12:41:22.637832,479392885,841,221,5.74666985772,-17.959377837375,15.413496509025,2,1,18
+2025-03-11T12:41:22.762832,479392885,841,221,6.2596813356,-19.12362320925,16.34014236258,2,1,18
+2025-03-11T12:41:22.887832,479392885,841,221,6.75857323152,-20.25091167282,17.201881344735,2,1,18
+2025-03-11T12:41:23.012832,479392885,841,221,7.21981290888,-21.299655190005,18.02616421518,2,1,18
+2025-03-11T12:41:23.137832,479392885,841,221,7.65751994964,-22.28834284533,18.785398170015,2,1,18
+2025-03-11T12:41:23.262832,479392885,841,221,8.06698782648,-23.249286243495,19.50746405985,2,1,18
+2025-03-11T12:41:23.387832,479392885,841,221,8.45762959404,-24.1178621751,20.19666170466,2,1,18
+2025-03-11T12:41:23.512832,479392885,841,221,8.80591261572,-24.89403520557,20.81135911266,2,1,18
+2025-03-11T12:41:23.637832,479392885,841,221,9.11654341884,-25.60551415749,21.36095270811,2,1,18
+2025-03-11T12:41:23.762832,479392885,841,221,9.39893505804,-26.26154711658,21.859371885015,2,1,18
+2025-03-11T12:41:23.887832,479392885,841,221,9.63896795136,-26.834411086425,22.30181996067,2,1,18
+2025-03-11T12:41:24.012832,479392885,841,221,9.86488126272,-27.32876554446,22.70224274625,2,1,18
+2025-03-11T12:41:24.137832,479392885,841,221,10.06726193748,-27.744596316855,23.014418696145,2,1,18
+2025-03-11T12:41:24.262832,479392885,841,221,10.20845775708,-28.08184670829,23.265987010605,2,1,18
+2025-03-11T12:41:24.387832,479392885,841,221,10.3308274674,-28.345197456945,23.470924063995,2,1,18
+2025-03-11T12:41:24.512832,479392885,841,221,10.41554495916,-28.502301523545,23.610538301085,2,1,18
+2025-03-11T12:41:24.637832,479392885,841,221,10.44378412308,-28.613150987715,23.68048519269,2,1,18
+2025-03-11T12:41:24.762832,479392885,841,221,10.44378412308,-28.64546967933,23.68065552894,2,1,18
+2025-03-11T12:41:24.887832,479392885,841,221,10.41554495916,-28.566938906775,23.610878973585,2,1,18
+2025-03-11T12:41:25.012832,479392885,841,221,10.36377315864,-28.40065053669,23.489767851165,2,1,18
+2025-03-11T12:41:25.137832,479392885,841,221,10.25081650296,-28.165015697535,23.31733799484,2,1,18
+2025-03-11T12:41:25.262832,479392885,841,221,10.119033738,-27.83701339182,23.06583872334,2,1,18
+2025-03-11T12:41:25.387832,479392885,841,221,9.94959875448,-27.453550919445,22.753904423805,2,1,18
+2025-03-11T12:41:25.512832,479392885,841,221,9.72368544312,-26.973047329245,22.390515575595,2,1,18
+2025-03-11T12:41:25.637832,479392885,841,221,9.49306560444,-26.40019753323,21.96656834346,2,1,18
+2025-03-11T12:41:25.762832,479392885,841,221,9.22008701988,-25.79034830742,21.477653113545,2,1,18
+2025-03-11T12:41:25.887832,479392885,841,221,8.92357579872,-25.08350757219,20.918874181005,2,1,18
+2025-03-11T12:41:26.012756,479392889,836,222,8.57999930436,-24.2934907608,20.31797431053,2,1,18
+2025-03-11T12:41:26.137756,479392889,836,222,8.22230322804,-23.448049217325,19.6659305847,2,1,18
+2025-03-11T12:41:26.262756,479392889,836,222,7.80812882388,-22.533268291695,18.944097844635,2,1,18
+2025-03-11T12:41:26.387756,479392889,836,222,7.37042178312,-21.549197592315,18.19412845758,2,1,18
+2025-03-11T12:41:26.512756,479392889,836,222,6.91388863308,-20.50507811799,17.38374045966,2,1,18
+2025-03-11T12:41:26.637756,479392889,836,222,6.4244097918,-19.40550556392,16.531408089495,2,1,18
+2025-03-11T12:41:26.762756,479392889,836,222,5.91610484124,-18.236650323015,15.63246879201,2,1,18
+2025-03-11T12:41:26.887756,479392889,836,222,5.39838683604,-17.01237743694,14.6823958269,2,1,18
+2025-03-11T12:41:27.012756,479392889,836,222,4.83360355764,-15.769565857935,13.699782830385,2,1,18
+2025-03-11T12:41:27.137756,479392889,836,222,4.24528764264,-14.452847549235,12.6797686191,2,1,18
+2025-03-11T12:41:27.262756,479392889,836,222,3.65226520032,-13.09918650606,11.641069082025,2,1,18
+2025-03-11T12:41:27.387756,479392889,836,222,3.0357101214,-11.72702220453,10.560640218165,2,1,18
+2025-03-11T12:41:27.512756,479392889,836,222,2.41444851516,-10.308681256635,9.452237126985,2,1,18
+2025-03-11T12:41:27.637756,479392889,836,222,1.7884803816,-8.84878061832,8.32974449328,2,1,18
+2025-03-11T12:41:27.762756,479392889,836,222,1.13897961144,-7.34267498598,7.18385699835,2,1,18
+2025-03-11T12:41:27.887756,479392889,836,222,0.46123967736,-5.822675964315,6.005494556685,2,1,18
+2025-03-11T12:41:28.012756,479392889,836,222,-0.20238067476,-4.302698203395,4.813302327165,2,1,18
+2025-03-11T12:41:28.137756,479392889,836,222,-0.8942401908,-2.754976185315,3.620902968765,2,1,18
+2025-03-11T12:41:28.262756,479392889,836,222,-1.5766866522,-1.198034429175,2.40537473325,2,1,18
+2025-03-11T12:41:28.387756,479392889,836,222,-2.26854616824,0.368155412685,1.189777454775,2,1,18
+2025-03-11T12:41:28.512756,479392889,836,222,-2.96040568428,1.9297282986,-0.00731502189,2,1,18
+2025-03-11T12:41:28.637756,479392889,836,222,-3.647558673,3.486677141655,-1.21823332812,2,1,18
+2025-03-11T12:41:28.762756,479392889,836,222,-4.31117902512,5.03897359419,-2.42907636195,2,1,18
+2025-03-11T12:41:28.887756,479392889,836,222,-4.9889189592,6.605142175305,-3.626162609175,2,1,18
+2025-03-11T12:41:29.012756,479392889,836,222,-5.67607194792,8.13438928269,-4.81383432783,2,1,18
+2025-03-11T12:41:29.137756,479392889,836,222,-6.33498577272,9.64974300075,-5.982891450795,2,1,18
+2025-03-11T12:41:29.262756,479392889,836,222,-6.9891930702,11.128153984335,-7.142503482,2,1,18
+2025-03-11T12:41:29.387756,479392889,836,222,-7.63398731304,12.57884905842,-8.26960831614,2,1,18
+2025-03-11T12:41:29.512756,479392889,836,222,-8.25054239196,14.011033787235,-9.38731445487,2,1,18
+2025-03-11T12:41:29.637756,479392889,836,222,-8.86709747088,15.401665912545,-10.472460770745,2,1,18
+2025-03-11T12:41:29.762756,479392889,836,222,-9.4601199132,16.74609304383,-11.506491523305,2,1,18
+2025-03-11T12:41:29.887756,479392889,836,222,-10.02960971892,18.07201691676,-12.50803318311,2,1,18
+2025-03-11T12:41:30.012695,479392893,832,223,-10.59439299732,19.333296319545,-13.48612339761,2,1,18
+2025-03-11T12:41:30.137695,479392893,832,223,-11.13564363912,20.548370728305,-14.431578516855,2,1,18
+2025-03-11T12:41:30.262695,479392893,832,223,-11.63924206236,21.70336801446,-15.33043462536,2,1,18
+2025-03-11T12:41:30.387695,479392893,832,223,-12.10048173972,22.798281091095,-16.182681535395,2,1,18
+2025-03-11T12:41:30.512695,479392893,832,223,-12.5664279444,23.84241473925,-16.98846979176,2,1,18
+2025-03-11T12:41:30.637695,479392893,832,223,-12.99472193052,24.803386485075,-17.738297134605,2,1,18
+2025-03-11T12:41:30.762695,479392893,832,223,-13.39477675272,25.713529194015,-18.455454860715,2,1,18
+2025-03-11T12:41:30.887695,479392893,832,223,-13.78541852028,26.568254257785,-19.107618568155,2,1,18
+2025-03-11T12:41:31.012695,479392893,832,223,-14.11016890536,27.35362576557,-19.70845335396,2,1,18
+2025-03-11T12:41:31.137695,479392893,832,223,-14.4255062358,28.028176156845,-20.262482584155,2,1,18
+2025-03-11T12:41:31.262695,479392893,832,223,-14.70319134768,28.661117249295,-20.737669319505,2,1,18
+2025-03-11T12:41:31.387695,479392893,832,223,-14.943224241,29.21551339536,-21.156919475085,2,1,18
+2025-03-11T12:41:31.512695,479392893,832,223,-15.16913755236,29.682166117725,-21.51561520503,2,1,18
+2025-03-11T12:41:31.637695,479392893,832,223,-15.33857253588,30.061011634155,-21.81366481977,2,1,18
+2025-03-11T12:41:31.762695,479392893,832,223,-15.47035530084,30.393630895815,-22.060568308005,2,1,18
+2025-03-11T12:41:31.887695,479392893,832,223,-15.57389890188,30.62925156114,-22.265318607975,2,1,18
+2025-03-11T12:41:32.012695,479392893,832,223,-15.63979028436,30.772476412245,-22.358617922745,2,1,18
+2025-03-11T12:41:32.137695,479392893,832,223,-15.6727359756,30.823312536045,-22.39129772721,2,1,18
+2025-03-11T12:41:32.262695,479392893,832,223,-15.68214903024,30.83717757771,-22.39139110392,2,1,18
+2025-03-11T12:41:32.387695,479392893,832,223,-15.63508375704,30.74476758966,-22.330741030425,2,1,18
+2025-03-11T12:41:32.512695,479392893,832,223,-15.55977931992,30.55074204933,-22.18633238178,2,1,18
+2025-03-11T12:41:32.637695,479392893,832,223,-15.4374096096,30.28277434473,-21.99061122867,2,1,18
+2025-03-11T12:41:32.762695,479392893,832,223,-15.30562684464,29.954772039015,-21.71139125508,2,1,18
+2025-03-11T12:41:32.887695,479392893,832,223,-15.12677880648,29.53435974525,-21.390001676055,2,1,18
+2025-03-11T12:41:33.012695,479392893,832,223,-14.90557202244,29.026161506295,-20.989516076955,2,1,18
+2025-03-11T12:41:33.137695,479392893,832,223,-14.65141954716,28.43019149598,-20.551535886375,2,1,18
+2025-03-11T12:41:33.262695,479392893,832,223,-14.3784409626,27.81110835828,-20.048711637915,2,1,18
+2025-03-11T12:41:33.387695,479392893,832,223,-14.05839710484,27.08114740875,-19.489760097975,2,1,18
+2025-03-11T12:41:33.512695,479392893,832,223,-13.6959945012,26.27263442592,-18.865621556505,2,1,18
+2025-03-11T12:41:33.637695,479392893,832,223,-13.3194723156,25.41331366695,-18.19036349343,2,1,18
+2025-03-11T12:41:33.762695,479392893,832,223,-12.88176527484,24.461561659185,-17.468285144715,2,1,18
+2025-03-11T12:41:33.887695,479392893,832,223,-12.4487647614,23.46826413483,-16.69979680983,2,1,18
+2025-03-11T12:41:34.012634,479392897,828,224,-11.99693813868,22.42415174742,-15.87093853158,2,1,18
+2025-03-11T12:41:34.137634,479392897,828,224,-11.50275277008,21.306104282655,-15.000018170625,2,1,18
+2025-03-11T12:41:34.262634,479392897,828,224,-10.98032823756,20.118759957225,-14.068610155845,2,1,18
+2025-03-11T12:41:34.387634,479392897,828,224,-10.4484906504,18.88061494257,-13.10457327525,2,1,18
+2025-03-11T12:41:34.512634,479392897,828,224,-9.87900084468,17.623945408815,-12.121877089755,2,1,18
+2025-03-11T12:41:34.637634,479392897,828,224,-9.30009798432,16.302624318,-11.115719271225,2,1,18
+2025-03-11T12:41:34.762634,479392897,828,224,-8.707075542,14.912027627265,-10.044484245045,2,1,18
+2025-03-11T12:41:34.887634,479392897,828,224,-8.09993351772,13.49832489606,-8.963856752895,2,1,18
+2025-03-11T12:41:35.012634,479392897,828,224,-7.46455232952,12.07072877553,-7.85075431401,2,1,18
+2025-03-11T12:41:35.137634,479392897,828,224,-6.81975808668,10.6154167455,-6.719005029105,2,1,18
+2025-03-11T12:41:35.262634,479392897,828,224,-6.15613773456,9.109289852415,-5.563846736955,2,1,18
+2025-03-11T12:41:35.387634,479392897,828,224,-5.49722390976,7.58931917841,-4.390145163225,2,1,18
+2025-03-11T12:41:35.512634,479392897,828,224,-4.80536439372,6.05083107222,-3.197794472325,2,1,18
+2025-03-11T12:41:35.637634,479392897,828,224,-4.12291793232,4.51235713986,-1.99160380584,2,1,18
+2025-03-11T12:41:35.762634,479392897,828,224,-3.44517799824,2.9415716028,-0.776012756805,2,1,18
+2025-03-11T12:41:35.887634,479392897,828,224,-2.7533184822,1.36614784905,0.43963318917,2,1,18
+2025-03-11T12:41:36.012634,479392897,828,224,-2.06616549348,-0.19541794995,1.627475244075,2,1,18
+2025-03-11T12:41:36.137634,479392897,828,224,-1.38371903208,-1.75235970609,2.847623596605,2,1,18
+2025-03-11T12:41:36.262634,479392897,828,224,-0.705979098,-3.281592639645,4.05375540786,2,1,18
+2025-03-11T12:41:36.387634,479392897,828,224,-0.02823916392,-4.83852730887,5.26465333863,2,1,18
+2025-03-11T12:41:36.512634,479392897,828,224,0.63067466088,-6.35388102693,6.44757081264,2,1,18
+2025-03-11T12:41:36.637634,479392897,828,224,1.29900154032,-7.84154718315,7.60264195752,2,1,18
+2025-03-11T12:41:36.762634,479392897,828,224,1.94850231048,-9.35688672738,8.753198236965,2,1,18
+2025-03-11T12:41:36.887634,479392897,828,224,2.59329655332,-10.798347889575,9.861773935545,2,1,18
+2025-03-11T12:41:37.012634,479392897,828,224,3.20514510492,-12.21667466364,10.951676183205,2,1,18
+2025-03-11T12:41:37.137634,479392897,828,224,3.8122871292,-13.58882479134,12.02746455459,2,1,18
+2025-03-11T12:41:37.262634,479392897,828,224,4.40530957152,-14.914784098845,13.07063820618,2,1,18
+2025-03-11T12:41:37.387634,479392897,828,224,4.97950590456,-16.21301332302,14.05818370017,2,1,18
+2025-03-11T12:41:37.512634,479392897,828,224,5.52075654636,-17.488108159065,15.01781550921,2,1,18
+2025-03-11T12:41:37.637634,479392897,828,224,6.0714202428,-18.68011196193,15.94930898412,2,1,18
+2025-03-11T12:41:37.762634,479392897,828,224,6.5656056114,-19.816627250475,16.83418703112,2,1,18
+2025-03-11T12:41:37.887634,479392897,828,224,7.04567139804,-20.91156867477,17.67261434103,2,1,18
+2025-03-11T12:41:38.012573,479392901,824,225,7.49749802076,-21.9372132384,18.47365458219,2,1,18
+2025-03-11T12:41:38.137573,479392901,824,225,7.92108547956,-22.89817789731,19.20961138626,2,1,18
+2025-03-11T12:41:38.262573,479392901,824,225,8.30231419248,-23.775973566975,19.894217206095,2,1,18
+2025-03-11T12:41:38.387573,479392901,824,225,8.64589068684,-24.584458202145,20.54141558172,2,1,18
+2025-03-11T12:41:38.512573,479392901,824,225,8.9894671812,-25.346773277865,21.123688981635,2,1,18
+2025-03-11T12:41:38.637573,479392901,824,225,9.30480451164,-26.016706713195,21.645353058975,2,1,18
+2025-03-11T12:41:38.762573,479392901,824,225,9.56837004156,-26.617307853285,22.120338894885,2,1,18
+2025-03-11T12:41:38.887573,479392901,824,225,9.77545724364,-27.143952655275,22.52551138281,2,1,18
+2025-03-11T12:41:39.012573,479392901,824,225,9.9778379184,-27.58748516334,22.874794271325,2,1,18
+2025-03-11T12:41:39.137573,479392901,824,225,10.15668595656,-27.9663448536,23.15900391048,2,1,18
+2025-03-11T12:41:39.262573,479392901,824,225,10.27905566688,-28.238929514145,23.396330450475,2,1,18
+2025-03-11T12:41:39.387573,479392901,824,225,10.38730579524,-28.456089442605,23.545552198995,2,1,18
+2025-03-11T12:41:39.512573,479392901,824,225,10.4484906504,-28.580839383015,23.64336410805,2,1,18
+2025-03-11T12:41:39.637573,479392901,824,225,10.45319717772,-28.631632985325,23.67136266912,2,1,18
+2025-03-11T12:41:39.762573,479392901,824,225,10.43437106844,-28.594668990105,23.629546195065,2,1,18
+2025-03-11T12:41:39.887573,479392901,824,225,10.39201232256,-28.4745643533,23.55027983874,2,1,18
+2025-03-11T12:41:40.012573,479392901,824,225,10.29788177616,-28.275893509365,23.405806105425,2,1,18
+2025-03-11T12:41:40.137573,479392901,824,225,10.18021859316,-27.994082023845,23.18692155372,2,1,18
+2025-03-11T12:41:40.262573,479392901,824,225,10.01549013696,-27.638328374055,22.87976356143,2,1,18
+2025-03-11T12:41:40.387573,479392901,824,225,9.81781598952,-27.18095208507,22.53503797641,2,1,18
+2025-03-11T12:41:40.512573,479392901,824,225,9.59660920548,-26.64966906639,22.157531293635,2,1,18
+2025-03-11T12:41:40.637573,479392901,824,225,9.3424567302,-26.053699056075,21.67797004992,2,1,18
+2025-03-11T12:41:40.762573,479392901,824,225,9.05535856368,-25.374574230345,21.133217846385,2,1,18
+2025-03-11T12:41:40.887573,479392901,824,225,8.72590165128,-24.626131283205,20.564908361955,2,1,18
+2025-03-11T12:41:41.012573,479392901,824,225,8.354085993,-23.82222108249,19.913053076685,2,1,18
+2025-03-11T12:41:41.137573,479392901,824,225,7.9540311708,-22.93054619733,19.223713387665,2,1,18
+2025-03-11T12:41:41.262573,479392901,824,225,7.54456329396,-21.96498584322,18.478522579005,2,1,18
+2025-03-11T12:41:41.387573,479392901,824,225,7.1068562532,-20.930128628445,17.695944701595,2,1,18
+2025-03-11T12:41:41.512573,479392901,824,225,6.63149699388,-19.86751298268,16.857697915665,2,1,18
+2025-03-11T12:41:41.637573,479392901,824,225,6.14672467992,-18.749479691745,15.982177813155,2,1,18
+2025-03-11T12:41:41.762573,479392901,824,225,5.61488709276,-17.55750423654,15.05534520618,2,1,18
+2025-03-11T12:41:41.887573,479392901,824,225,5.07363645096,-16.300877224275,14.07733026408,2,1,18
+2025-03-11T12:41:42.012497,479392905,819,226,4.49944011792,-14.998031044155,13.075900085295,2,1,18
+2025-03-11T12:41:42.137497,479392905,819,226,3.92524378488,-13.667483128365,12.03736296789,2,1,18
+2025-03-11T12:41:42.262497,479392905,819,226,3.31339523328,-12.290708957805,10.97540042607,2,1,18
+2025-03-11T12:41:42.387497,479392905,819,226,2.70154668168,-10.88161609563,9.87630661188,2,1,18
+2025-03-11T12:41:42.512497,479392905,819,226,2.05204591152,-9.417063066795,8.76759905682,2,1,18
+2025-03-11T12:41:42.637497,479392905,819,226,1.39313208672,-7.93402804035,7.62181285518,2,1,18
+2025-03-11T12:41:42.762497,479392905,819,226,0.73892478924,-6.427915321095,6.48515540655,2,1,18
+2025-03-11T12:41:42.887497,479392905,819,226,0.08471749176,-4.91256868995,5.30224812027,2,1,18
+2025-03-11T12:41:43.012497,479392905,819,226,-0.57890286036,-3.38335701714,4.096146872205,2,1,18
+2025-03-11T12:41:43.137497,479392905,819,226,-1.26134932176,-1.840266128835,2.894551988985,2,1,18
+2025-03-11T12:41:43.262497,479392905,819,226,-1.95791536512,-0.269452244115,1.683540306045,2,1,18
+2025-03-11T12:41:43.387497,479392905,819,226,-2.66389446312,1.30599277038,0.45862356285,2,1,18
+2025-03-11T12:41:43.512497,479392905,819,226,-3.35104745184,2.86755856938,-0.7430788431,2,1,18
+2025-03-11T12:41:43.637497,479392905,819,226,-4.0476134952,4.424521586265,-1.95401752479,2,1,18
+2025-03-11T12:41:43.762497,479392905,819,226,-4.72535342928,5.976839299545,-3.151030770765,2,1,18
+2025-03-11T12:41:43.887497,479392905,819,226,-5.38426725408,7.529128665165,-4.334142914775,2,1,18
+2025-03-11T12:41:44.012497,479392905,819,226,-6.04318107888,9.04909933917,-5.52170483955,2,1,18
+2025-03-11T12:41:44.137497,479392905,819,226,-6.706801431,10.536758408475,-6.6767657967,2,1,18
+2025-03-11T12:41:44.262497,479392905,819,226,-7.35159567384,12.001304350395,-7.817803983135,2,1,18
+2025-03-11T12:41:44.387497,479392905,819,226,-7.97285728008,13.433496166125,-8.93090019258,2,1,18
+2025-03-11T12:41:44.512497,479392905,819,226,-8.59882541364,14.82875942121,-10.016091217665,2,1,18
+2025-03-11T12:41:44.637497,479392905,819,226,-9.2012609106,16.21475332983,-11.078082051525,2,1,18
+2025-03-11T12:41:44.762497,479392905,819,226,-9.79428335292,17.540712637335,-12.09815511804,2,1,18
+2025-03-11T12:41:44.887497,479392905,819,226,-10.34965357668,18.82044569007,-13.10404299417,2,1,18
+2025-03-11T12:41:45.012497,479392905,819,226,-10.90031727312,20.04476818455,-14.058807390405,2,1,18
+2025-03-11T12:41:45.137497,479392905,819,226,-11.40862222368,21.22747429329,-14.96705992317,2,1,18
+2025-03-11T12:41:45.262497,479392905,819,226,-11.9075141196,22.350145800915,-15.83339468859,2,1,18
+2025-03-11T12:41:45.387497,479392905,819,226,-12.354634215,23.41271892519,-16.65309988008,2,1,18
+2025-03-11T12:41:45.512497,479392905,819,226,-12.80646083772,24.41989566504,-17.421701967135,2,1,18
+2025-03-11T12:41:45.637497,479392905,819,226,-13.21122218724,25.366981108455,-18.148304785005,2,1,18
+2025-03-11T12:41:45.762497,479392905,819,226,-13.61598353676,26.244812212695,-18.828341426475,2,1,18
+2025-03-11T12:41:45.887497,479392905,819,226,-13.97367961308,27.039467240775,-19.45701689598,2,1,18
+2025-03-11T12:41:46.012436,479392909,815,227,-14.30313652548,27.769442364135,-20.01598881138,2,1,18
+2025-03-11T12:41:46.137436,479392909,815,227,-14.57611511004,28.43007810534,-20.52827229762,2,1,18
+2025-03-11T12:41:46.262436,479392909,815,227,-14.8490936946,29.016842551425,-20.980104922665,2,1,18
+2025-03-11T12:41:46.387436,479392909,815,227,-15.07030047864,29.49733905471,-21.37582440225,2,1,18
+2025-03-11T12:41:46.512436,479392909,815,227,-15.2491485168,29.917751348475,-21.697213981275,2,1,18
+2025-03-11T12:41:46.637436,479392909,815,227,-15.39975739104,30.26424982563,-21.95347145571,2,1,18
+2025-03-11T12:41:46.762436,479392909,815,227,-15.51742057404,30.54606131115,-22.1677358904,2,1,18
+2025-03-11T12:41:46.887436,479392909,815,227,-15.6021380658,30.73086711342,-22.30749612999,2,1,18
+2025-03-11T12:41:47.012436,479392909,815,227,-15.65390986632,30.823284188385,-22.37277650823,2,1,18
+2025-03-11T12:41:47.137436,479392909,815,227,-15.6727359756,30.83716340388,-22.39137072846,2,1,18
+2025-03-11T12:41:47.262436,479392909,815,227,-15.63979028436,30.7678594563,-22.34473323795,2,1,18
+2025-03-11T12:41:47.387436,479392909,815,227,-15.5786054292,30.620024736165,-22.2329393091,2,1,18
+2025-03-11T12:41:47.512436,479392909,815,227,-15.47976835548,30.40749593748,-22.0560415677,2,1,18
+2025-03-11T12:41:47.637436,479392909,815,227,-15.34798559052,30.08411058771,-21.83228733204,2,1,18
+2025-03-11T12:41:47.762436,479392909,815,227,-15.16913755236,29.700633941505,-21.51571254003,2,1,18
+2025-03-11T12:41:47.887436,479392909,815,227,-14.95734382296,29.22938552394,-21.138542571465,2,1,18
+2025-03-11T12:41:48.012436,479392909,815,227,-14.71260440232,28.688833158795,-20.72397534642,2,1,18
+2025-03-11T12:41:48.137436,479392909,815,227,-14.45845192704,28.05592750092,-20.253459666735,2,1,18
+2025-03-11T12:41:48.262436,479392909,815,227,-14.16194070588,27.344469809745,-19.703896634475,2,1,18
+2025-03-11T12:41:48.387436,479392909,815,227,-13.82777726616,26.582168907855,-19.11240337599,2,1,18
+2025-03-11T12:41:48.512436,479392909,815,227,-13.44654855324,25.75977670953,-18.465050497275,2,1,18
+2025-03-11T12:41:48.637436,479392909,815,227,-13.04649373104,24.854250956535,-17.747917104915,2,1,18
+2025-03-11T12:41:48.762436,479392909,815,227,-12.60878669028,23.88403112499,-16.984160368065,2,1,18
+2025-03-11T12:41:48.887436,479392909,815,227,-12.1663731222,22.8491668233,-16.18771195188,2,1,18
+2025-03-11T12:41:49.012436,479392909,815,227,-11.68630733556,21.74037453117,-15.344591523705,2,1,18
+2025-03-11T12:41:49.137436,479392909,815,227,-11.17329585768,20.576129159295,-14.441046255225,2,1,18
+2025-03-11T12:41:49.262436,479392909,815,227,-10.6367517432,19.38876357312,-13.5234680283,2,1,18
+2025-03-11T12:41:49.387436,479392909,815,227,-10.10020762872,18.127526691825,-12.540818823165,2,1,18
+2025-03-11T12:41:49.512436,479392909,815,227,-9.53542435032,16.82931164148,-11.53019311956,2,1,18
+2025-03-11T12:41:49.637436,479392909,815,227,-8.94710843532,15.47565768522,-10.473023302155,2,1,18
+2025-03-11T12:41:49.762436,479392909,815,227,-8.3305533564,14.080408603965,-9.39709288656,2,1,18
+2025-03-11T12:41:49.887436,479392909,815,227,-7.69987869552,12.64358565846,-8.293192201935,2,1,18
+2025-03-11T12:41:50.012375,479392913,811,228,-7.05037792536,11.20211740935,-7.16150573055,2,1,18
+2025-03-11T12:41:50.137375,479392913,811,228,-6.40558368252,9.723720599595,-6.00653419182,2,1,18
+2025-03-11T12:41:50.262375,479392913,811,228,-5.73255027576,8.212962576735,-4.8328507224,2,1,18
+2025-03-11T12:41:50.387375,479392913,811,228,-5.059516869,6.674502818205,-3.64978101645,2,1,18
+2025-03-11T12:41:50.512375,479392913,811,228,-4.39118998956,5.149901014425,-2.45755426545,2,1,18
+2025-03-11T12:41:50.637375,479392913,811,228,-3.71345005548,3.60220025709,-1.25594523621,2,1,18
+2025-03-11T12:41:50.762375,479392913,811,228,-3.02629706676,2.036017502145,-0.04497826248,2,1,18
+2025-03-11T12:41:50.887375,479392913,811,228,-2.33443755072,0.451359836505,1.170716350995,2,1,18
+2025-03-11T12:41:51.012375,479392913,811,228,-1.647284562,-1.11482291844,2.36782297368,2,1,18
+2025-03-11T12:41:51.137375,479392913,811,228,-0.96954462792,-2.653289763885,3.57862356945,2,1,18
+2025-03-11T12:41:51.262375,479392913,811,228,-0.28709816652,-4.20561456408,4.78026712017,2,1,18
+2025-03-11T12:41:51.387375,479392913,811,228,0.39534829488,-5.730237628605,5.9540439663,2,1,18
+2025-03-11T12:41:51.512375,479392913,811,228,1.04955559236,-7.23635034786,7.13690258508,2,1,18
+2025-03-11T12:41:51.637375,479392913,811,228,1.70846941716,-8.73323624214,8.287381904985,2,1,18
+2025-03-11T12:41:51.762375,479392913,811,228,2.33914407804,-10.22084570304,9.423891079965,2,1,18
+2025-03-11T12:41:51.887375,479392913,811,228,2.97452526624,-11.64844182357,10.513892933775,2,1,18
+2025-03-11T12:41:52.012375,479392913,811,228,3.59108034516,-13.01137221321,11.585032896105,2,1,18
+2025-03-11T12:41:52.137375,479392913,811,228,4.19822236944,-14.36505451713,12.637623347415,2,1,18
+2025-03-11T12:41:52.262375,479392913,811,228,4.7771252298,-15.686375607945,13.653021399975,2,1,18
+2025-03-11T12:41:52.387375,479392913,811,228,5.3183758716,-16.956853488045,14.631109343325,2,1,18
+2025-03-11T12:41:52.512375,479392913,811,228,5.85491998608,-18.15345298611,15.571836822825,2,1,18
+2025-03-11T12:41:52.637375,479392913,811,228,6.36793146396,-19.32231531393,16.46154607401,2,1,18
+2025-03-11T12:41:52.762375,479392913,811,228,6.8479972506,-20.43110760606,17.332387204275,2,1,18
+2025-03-11T12:41:52.887375,479392913,811,228,7.30923692796,-21.479851123245,18.142809723675,2,1,18
+2025-03-11T12:41:53.012375,479392913,811,228,7.75165049604,-22.487013689265,18.91139143527,2,1,18
+2025-03-11T12:41:53.137375,479392913,811,228,8.1658249002,-23.420262438675,19.614841042275,2,1,18
+2025-03-11T12:41:53.262375,479392913,811,228,8.5188144492,-24.26107993929,20.276090480655,2,1,18
+2025-03-11T12:41:53.387375,479392913,811,228,8.86239094356,-25.018778059065,20.881440131895,2,1,18
+2025-03-11T12:41:53.512375,479392913,811,228,9.18243480132,-25.70718640509,21.42631231704,2,1,18
+2025-03-11T12:41:53.637375,479392913,811,228,9.46953296784,-26.35860949515,21.92009723091,2,1,18
+2025-03-11T12:41:53.762375,479392913,811,228,9.7189789158,-26.913019815045,22.35784823001,2,1,18
+2025-03-11T12:41:53.887375,479392913,811,228,9.94018569984,-27.41198414211,22.73980469355,2,1,18
+2025-03-11T12:41:54.012314,479392917,807,229,10.11432721068,-27.83238934896,23.0473237338,2,1,18
+2025-03-11T12:41:54.137314,479392917,807,229,10.2602295576,-28.16964682731,23.29890223599,2,1,18
+2025-03-11T12:41:54.262314,479392917,807,229,10.36847968596,-28.391423711715,23.47586902035,2,1,18
+2025-03-11T12:41:54.387314,479392917,807,229,10.43907759576,-28.553123473515,23.60623679397,2,1,18
+2025-03-11T12:41:54.512314,479392917,807,229,10.46261023236,-28.60856237943,23.675881492845,2,1,18
+2025-03-11T12:41:54.637314,479392917,807,229,10.45790370504,-28.599321380625,23.66196228657,2,1,18
+2025-03-11T12:41:54.762314,479392917,807,229,10.4249580138,-28.5254004771,23.58757976022,2,1,18
+2025-03-11T12:41:54.887314,479392917,807,229,10.354360104,-28.35446680341,23.452543202085,2,1,18
+2025-03-11T12:41:55.012314,479392917,807,229,10.24140344832,-28.09574718453,23.266131325965,2,1,18
+2025-03-11T12:41:55.137314,479392917,807,229,10.10491415604,-27.763120835955,23.00073718194,2,1,18
+2025-03-11T12:41:55.262314,479392917,807,229,9.9307726452,-27.370417364775,22.69336414419,2,1,18
+2025-03-11T12:41:55.387314,479392917,807,229,9.70956586116,-26.88992086149,22.306884898635,2,1,18
+2025-03-11T12:41:55.512314,479392917,807,229,9.46482644052,-26.32628371662,21.85523506872,2,1,18
+2025-03-11T12:41:55.637314,479392917,807,229,9.17302174668,-25.674853539645,21.366060084135,2,1,18
+2025-03-11T12:41:55.762314,479392917,807,229,8.8718039982,-24.95877180561,20.80260217935,2,1,18
+2025-03-11T12:41:55.887314,479392917,807,229,8.52822750384,-24.16875499422,20.192462074845,2,1,18
+2025-03-11T12:41:56.012314,479392917,807,229,8.14699879092,-23.300193236445,19.52638539057,2,1,18
+2025-03-11T12:41:56.137314,479392917,807,229,7.7422374414,-22.36234170492,18.795211123185,2,1,18
+2025-03-11T12:41:56.262314,479392917,807,229,7.3186499826,-21.359824442505,18.02669449626,2,1,18
+2025-03-11T12:41:56.387314,479392917,807,229,6.85741030524,-20.31108092532,17.202411625815,2,1,18
+2025-03-11T12:41:56.512314,479392917,807,229,6.36322493664,-19.1976504165,16.354616183685,2,1,18
+2025-03-11T12:41:56.637314,479392917,807,229,5.84080040412,-18.01030609107,15.44630875398,2,1,18
+2025-03-11T12:41:56.762314,479392917,807,229,5.294843235,-16.79060763945,14.491578879225,2,1,18
+2025-03-11T12:41:56.887314,479392917,807,229,4.73947301124,-15.53395936644,13.49967302289,2,1,18
+2025-03-11T12:41:57.012314,479392917,807,229,4.17468973284,-14.21265953637,12.479685416505,2,1,18
+2025-03-11T12:41:57.137314,479392917,807,229,3.58166729052,-12.858998493195,11.42250541137,2,1,18
+2025-03-11T12:41:57.262314,479392917,807,229,2.95569915696,-11.43603350244,10.346408617815,2,1,18
+2025-03-11T12:41:57.387314,479392917,807,229,2.32502449608,-9.999210556935,9.247128050205,2,1,18
+2025-03-11T12:41:57.512314,479392917,807,229,1.6943498352,-8.539302831705,8.11538499474,2,1,18
+2025-03-11T12:41:57.637314,479392917,807,229,1.04014253772,-7.05165793623,6.94186394499,2,1,18
+2025-03-11T12:41:57.762314,479392917,807,229,0.36710913096,-5.536282957425,5.754295790775,2,1,18
+2025-03-11T12:41:57.887314,479392917,807,229,-0.31533733044,-3.988575113175,4.57577715888,2,1,18
+2025-03-11T12:41:58.012237,479392921,802,230,-0.98366420988,-2.44088852967,3.378808622115,2,1,18
+2025-03-11T12:41:58.137237,479392921,802,230,-1.65669761664,-0.88396094736,2.17254099609,2,1,18
+2025-03-11T12:41:58.262237,479392921,802,230,-2.36267671464,0.682250155245,0.96153327144,2,1,18
+2025-03-11T12:41:58.387237,479392921,802,230,-3.04512317604,2.23457495544,-0.24935051331,2,1,18
+2025-03-11T12:41:58.512237,479392921,802,230,-3.72756963744,3.786899755635,-1.464854415075,2,1,18
+2025-03-11T12:41:58.637237,479392921,802,230,-4.41472262616,5.34384859869,-2.675772721305,2,1,18
+2025-03-11T12:41:58.762237,479392921,802,230,-5.09716908756,6.88232253105,-3.86348291973,2,1,18
+2025-03-11T12:41:58.887237,479392921,802,230,-5.765495967,8.420775202665,-5.060402788995,2,1,18
+2025-03-11T12:41:59.012237,479392921,802,230,-6.41970326448,9.91765401003,-6.215492038185,2,1,18
+2025-03-11T12:41:59.137237,479392921,802,230,-7.06920403464,11.3960579067,-7.379713998675,2,1,18
+2025-03-11T12:41:59.262237,479392921,802,230,-7.71399827748,12.846752980785,-8.48371824774,2,1,18
+2025-03-11T12:41:59.387237,479392921,802,230,-8.3305533564,14.26046988582,-9.587466700425,2,1,18
+2025-03-11T12:41:59.512237,479392921,802,230,-8.94710843532,15.65110201113,-10.658752665255,2,1,18
+2025-03-11T12:41:59.637237,479392921,802,230,-9.54013087764,17.00014609836,-11.692807751565,2,1,18
+2025-03-11T12:41:59.762237,479392921,802,230,-10.10020762872,18.31682188557,-12.708140719455,2,1,18
+2025-03-11T12:41:59.887237,479392921,802,230,-10.6602843798,19.55962637766,-13.67226306018,2,1,18
+2025-03-11T12:42:00.012237,479392921,802,230,-11.18270891232,20.779289394705,-14.60384141121,2,1,18
+2025-03-11T12:42:00.137237,479392921,802,230,-11.68160080824,21.906577858275,-15.493301095455,2,1,18
+2025-03-11T12:42:00.262237,479392921,802,230,-12.1663731222,22.992292457595,-16.331689925595,2,1,18
+2025-03-11T12:42:00.387237,479392921,802,230,-12.61819974492,24.017937021225,-17.123489932725,2,1,18
+2025-03-11T12:42:00.512237,479392921,802,230,-13.04649373104,24.99737659083,-17.8826548446,2,1,18
+2025-03-11T12:42:00.637237,479392921,802,230,-13.44654855324,25.89828538788,-18.576663318135,2,1,18
+2025-03-11T12:42:00.762237,479392921,802,230,-13.8136576842,26.72989023735,-19.22403430116,2,1,18
+2025-03-11T12:42:00.887237,479392921,802,230,-14.1431145966,27.482950140435,-19.815468704415,2,1,18
+2025-03-11T12:42:01.012237,479392921,802,230,-14.4490388724,28.16672026977,-20.337185407545,2,1,18
+2025-03-11T12:42:01.137237,479392921,802,230,-14.72201745696,28.77656949558,-20.81686040343,2,1,18
+2025-03-11T12:42:01.262237,479392921,802,230,-14.9667568776,29.32173881667,-21.231451962225,2,1,18
+2025-03-11T12:42:01.387237,479392921,802,230,-15.16443102504,29.779115105655,-21.585417781275,2,1,18
+2025-03-11T12:42:01.512237,479392921,802,230,-15.32445295392,30.148712536365,-21.87877823604,2,1,18
+2025-03-11T12:42:01.637237,479392921,802,230,-15.44682266424,30.435148064745,-22.116177777285,2,1,18
+2025-03-11T12:42:01.762237,479392921,802,230,-15.5550727926,30.63845712537,-22.283806992615,2,1,18
+2025-03-11T12:42:01.887237,479392921,802,230,-15.61155112044,30.78628475859,-22.395590733735,2,1,18
+2025-03-11T12:42:02.012176,479392925,798,231,-15.63508375704,30.841723664505,-22.423654379475,2,1,18
+2025-03-11T12:42:02.137176,479392925,798,231,-15.63979028436,30.79556119197,-22.40956087866,2,1,18
+2025-03-11T12:42:02.262176,479392925,798,231,-15.58801848384,30.68929324917,-22.321106914095,2,1,18
+2025-03-11T12:42:02.387176,479392925,798,231,-15.50330099208,30.5044874469,-22.16748632346,2,1,18
+2025-03-11T12:42:02.512176,479392925,798,231,-15.38093128176,30.2365197423,-21.95328470229,2,1,18
+2025-03-11T12:42:02.637176,479392925,798,231,-15.2256158802,29.88078026634,-21.66462755352,2,1,18
+2025-03-11T12:42:02.762176,479392925,798,231,-15.04676784204,29.43728319285,-21.31077548664,2,1,18
+2025-03-11T12:42:02.887176,479392925,798,231,-14.80673494872,28.929056606235,-20.91948937065,2,1,18
+2025-03-11T12:42:03.012176,479392925,798,231,-14.55258247344,28.337703551865,-20.45381281173,2,1,18
+2025-03-11T12:42:03.137176,479392925,798,231,-14.27019083424,27.672436680885,-19.946104733295,2,1,18
+2025-03-11T12:42:03.262176,479392925,798,231,-13.96897308576,26.914802343345,-19.377807707745,2,1,18
+2025-03-11T12:42:03.387176,479392925,798,231,-13.59245090016,26.10626809977,-18.744398369055,2,1,18
+2025-03-11T12:42:03.512176,479392925,798,231,-13.21592871456,25.214628649185,-18.064349852715,2,1,18
+2025-03-11T12:42:03.637176,479392925,798,231,-12.80646083772,24.29062089858,-17.34247863288,2,1,18
+2025-03-11T12:42:03.762176,479392925,798,231,-12.34992768768,23.26958620398,-16.55069277177,2,1,18
+2025-03-11T12:42:03.887176,479392925,798,231,-11.87456842836,22.188502734435,-15.72158888487,2,1,18
+2025-03-11T12:42:04.012176,479392925,798,231,-11.37567653244,21.0750651387,-14.841442435905,2,1,18
+2025-03-11T12:42:04.137176,479392925,798,231,-10.86737158188,19.87389120618,-13.91461210008,2,1,18
+2025-03-11T12:42:04.262176,479392925,798,231,-10.31670788544,18.626483931975,-12.950485801065,2,1,18
+2025-03-11T12:42:04.387176,479392925,798,231,-9.766044189,17.3513749221,-11.953872680445,2,1,18
+2025-03-11T12:42:04.512176,479392925,798,231,-9.19184785596,16.0300609182,-10.92462446457,2,1,18
+2025-03-11T12:42:04.637176,479392925,798,231,-8.57999930436,14.639435879805,-9.87182915553,2,1,18
+2025-03-11T12:42:04.762176,479392925,798,231,-7.95873769812,13.23956275569,-8.777383750395,2,1,18
+2025-03-11T12:42:04.887176,479392925,798,231,-7.32335650992,11.798115767325,-7.659588193245,2,1,18
+2025-03-11T12:42:05.012176,479392925,798,231,-6.66444268512,10.30584682899,-6.513753324105,2,1,18
+2025-03-11T12:42:05.137176,479392925,798,231,-6.01494191496,8.81820902043,-5.3448625791,2,1,18
+2025-03-11T12:42:05.262176,479392925,798,231,-5.34661503552,7.288990260705,-4.17109196241,2,1,18
+2025-03-11T12:42:05.387176,479392925,798,231,-4.66416857412,5.750516328345,-2.97876164697,2,1,18
+2025-03-11T12:42:05.512176,479392925,798,231,-3.98172211272,4.18895761626,-1.772449311735,2,1,18
+2025-03-11T12:42:05.637176,479392925,798,231,-3.28986259668,2.63200168629,-0.561520817775,2,1,18
+2025-03-11T12:42:05.762176,479392925,798,231,-2.60741613528,1.05659210637,0.65410475274,2,1,18
+2025-03-11T12:42:05.887176,479392925,798,231,-1.91555661924,-0.51883164738,1.84665011364,2,1,18
+2025-03-11T12:42:06.012115,479392929,794,232,-1.22840363052,-2.075780490435,3.0668086539,2,1,18
+2025-03-11T12:42:06.137115,479392929,794,232,-0.55537022376,-3.623474160855,4.273027612425,2,1,18
+2025-03-11T12:42:06.262115,479392929,794,232,0.11295665568,-5.166543788415,5.465351698425,2,1,18
+2025-03-11T12:42:06.387115,479392929,794,232,0.79069658976,-6.65884107441,6.629707786545,2,1,18
+2025-03-11T12:42:06.512115,479392929,794,232,1.4590234692,-8.178825922245,7.78032915066,2,1,18
+2025-03-11T12:42:06.637115,479392929,794,232,2.10381771204,-9.63875490822,8.94444358842,2,1,18
+2025-03-11T12:42:06.762115,479392929,794,232,2.7297858456,-11.05710294303,10.066717218375,2,1,18
+2025-03-11T12:42:06.887115,479392929,794,232,3.35575397916,-12.470834021895,11.16124581249,2,1,18
+2025-03-11T12:42:07.012115,479392929,794,232,3.9770155854,-13.85223932223,12.23249329755,2,1,18
+2025-03-11T12:42:07.137115,479392929,794,232,4.5417988638,-15.205857843915,13.2572713572,2,1,18
+2025-03-11T12:42:07.262115,479392929,794,232,5.09716908756,-16.49482480854,14.249347549785,2,1,18
+2025-03-11T12:42:07.387115,479392929,794,232,5.647832784,-17.714530347075,15.20408761227,2,1,18
+2025-03-11T12:42:07.512115,479392929,794,232,6.17967037116,-18.89727189039,16.121631317715,2,1,18
+2025-03-11T12:42:07.637115,479392929,794,232,6.66914921244,-20.019929224185,16.978705473645,2,1,18
+2025-03-11T12:42:07.762115,479392929,794,232,7.13509541712,-21.087147652065,17.816956217865,2,1,18
+2025-03-11T12:42:07.887115,479392929,794,232,7.56809593056,-22.08967908831,18.608593805325,2,1,18
+2025-03-11T12:42:08.012115,479392929,794,232,8.01050949864,-23.046055138935,19.33994690955,2,1,18
+2025-03-11T12:42:08.137115,479392929,794,232,8.38703168424,-23.923843721685,20.015302307625,2,1,18
+2025-03-11T12:42:08.262115,479392929,794,232,8.74002123324,-24.741576442575,20.639469141135,2,1,18
+2025-03-11T12:42:08.387115,479392929,794,232,9.07418467296,-25.48079256474,21.22160049684,2,1,18
+2025-03-11T12:42:08.512115,479392929,794,232,9.3659893668,-26.150690565495,21.729353284485,2,1,18
+2025-03-11T12:42:08.637115,479392929,794,232,9.63426142404,-26.737447924665,22.1811757218,2,1,18
+2025-03-11T12:42:08.762115,479392929,794,232,9.85546820808,-27.25488007551,22.586330105415,2,1,18
+2025-03-11T12:42:08.887115,479392929,794,232,10.0484358282,-27.689164497855,22.912443365895,2,1,18
+2025-03-11T12:42:09.012115,479392929,794,232,10.19904470244,-28.031046019065,23.182536857625,2,1,18
+2025-03-11T12:42:09.137115,479392929,794,232,10.31670788544,-28.312857504585,23.406041526345,2,1,18
+2025-03-11T12:42:09.262115,479392929,794,232,10.41554495916,-28.502301523545,23.54123654586,2,1,18
+2025-03-11T12:42:09.387115,479392929,794,232,10.4484906504,-28.59469025085,23.629576758255,2,1,18
+2025-03-11T12:42:09.512115,479392929,794,232,10.46261023236,-28.61779629132,23.65282957527,2,1,18
+2025-03-11T12:42:09.637115,479392929,794,232,10.4484906504,-28.55775460329,23.620141854225,2,1,18
+2025-03-11T12:42:09.762115,479392929,794,232,10.4014253772,-28.42840896768,23.51309594058,2,1,18
+2025-03-11T12:42:09.887115,479392929,794,232,10.28846872152,-28.202008040415,23.33609463474,2,1,18
+2025-03-11T12:42:10.012054,479392933,790,233,10.1660990112,-27.906338600145,23.107886660025,2,1,18
+2025-03-11T12:42:10.137054,479392933,790,233,9.99195750036,-27.51825208491,22.828258658115,2,1,18
+2025-03-11T12:42:10.262054,479392933,790,233,9.78016377096,-27.056237579235,22.464997708095,2,1,18
+2025-03-11T12:42:10.387054,479392933,790,233,9.5542504596,-26.529564429585,22.04130400119,2,1,18
+2025-03-11T12:42:10.512054,479392933,790,233,9.28597840236,-25.91972229069,21.552398959005,2,1,18
+2025-03-11T12:42:10.637054,479392933,790,233,8.98476065388,-25.23595924827,21.01683209256,2,1,18
+2025-03-11T12:42:10.762054,479392933,790,233,8.6364776322,-24.47825404158,20.434572838665,2,1,18
+2025-03-11T12:42:10.887054,479392933,790,233,8.27407502856,-23.6235714993,19.782470257605,2,1,18
+2025-03-11T12:42:11.012054,479392933,790,233,7.87872673368,-22.713435877275,19.083803187285,2,1,18
+2025-03-11T12:42:11.137054,479392933,790,233,7.47396538416,-21.770967389805,18.347984469135,2,1,18
+2025-03-11T12:42:11.262054,479392933,790,233,7.0127257068,-20.73145778451,17.556091085295,2,1,18
+2025-03-11T12:42:11.387054,479392933,790,233,6.52324686552,-19.64111914233,16.708427499645,2,1,18
+2025-03-11T12:42:11.512054,479392933,790,233,6.01494191496,-18.47688085737,15.80951253591,2,1,18
+2025-03-11T12:42:11.637054,479392933,790,233,5.49722390976,-17.27569275102,14.88728194164,2,1,18
+2025-03-11T12:42:11.762054,479392933,790,233,4.96067979528,-16.014455869725,13.90925285352,2,1,18
+2025-03-11T12:42:11.887054,479392933,790,233,4.3770704076,-14.7346802955,12.898683733995,2,1,18
+2025-03-11T12:42:12.012054,479392933,790,233,3.76992838332,-13.394848859415,11.836926049905,2,1,18
+2025-03-11T12:42:12.137054,479392933,790,233,3.16749288636,-11.99500408296,10.756381746735,2,1,18
+2025-03-11T12:42:12.262054,479392933,790,233,2.5415247528,-10.58588996004,9.6711177204,2,1,18
+2025-03-11T12:42:12.387054,479392933,790,233,1.91085009192,-9.12598223481,8.55323501598,2,1,18
+2025-03-11T12:42:12.512054,479392933,790,233,1.25664279444,-7.63372038339,7.412030451585,2,1,18
+2025-03-11T12:42:12.637054,479392933,790,233,0.60714202428,-6.141465618885,6.238495255815,2,1,18
+2025-03-11T12:42:12.762054,479392933,790,233,-0.05647832784,-4.60763699013,5.04160990803,2,1,18
+2025-03-11T12:42:12.887054,479392933,790,233,-0.7295117346,-3.073794187545,3.844704184785,2,1,18
+2025-03-11T12:42:13.012054,479392933,790,233,-1.43078430528,-1.526057995635,2.652284450925,2,1,18
+2025-03-11T12:42:13.137054,479392933,790,233,-2.09911118472,0.035479455705,1.441382561865,2,1,18
+2025-03-11T12:42:13.262054,479392933,790,233,-2.78155764612,1.592421211845,0.23509456038,2,1,18
+2025-03-11T12:42:13.387054,479392933,790,233,-3.48753674412,3.15863231445,-0.971293047255,2,1,18
+2025-03-11T12:42:13.512054,479392933,790,233,-4.17468973284,4.715581157505,-2.172971119455,2,1,18
+2025-03-11T12:42:13.637054,479392933,790,233,-4.85713619424,6.2679059577,-3.383854904205,2,1,18
+2025-03-11T12:42:13.762054,479392933,790,233,-5.53958265564,7.792529022225,-4.585352452425,2,1,18
+2025-03-11T12:42:13.887054,479392933,790,233,-6.19849648044,9.317116652175,-5.73597777483,2,1,18
+2025-03-11T12:42:14.011993,479392937,786,234,-6.8479972506,10.813988372625,-6.90029707032,2,1,18
+2025-03-11T12:42:14.136993,479392937,786,234,-7.48808496612,12.264676359795,-8.04587218479,2,1,18
+2025-03-11T12:42:14.261993,479392937,786,234,-8.10464004504,13.7060950005,-9.15438675699,2,1,18
+2025-03-11T12:42:14.386993,479392937,786,234,-8.72119512396,15.1059610377,-10.24420185738,2,1,18
+2025-03-11T12:42:14.511993,479392937,786,234,-9.32363062092,16.468870166595,-11.301450905475,2,1,18
+2025-03-11T12:42:14.636993,479392937,786,234,-9.92135959056,17.79021960507,-12.298409240895,2,1,18
+2025-03-11T12:42:14.761993,479392937,786,234,-10.47672981432,19.05610178997,-13.294983881745,2,1,18
+2025-03-11T12:42:14.886993,479392937,786,234,-11.00386087416,20.27577189393,-14.24043277155,2,1,18
+2025-03-11T12:42:15.011993,479392937,786,234,-11.52157887936,21.453875220555,-15.13482099498,2,1,18
+2025-03-11T12:42:15.136993,479392937,786,234,-12.00635119332,22.59037633527,-16.00119819846,2,1,18
+2025-03-11T12:42:15.261993,479392937,786,234,-12.472297398,23.62989302748,-16.83006270615,2,1,18
+2025-03-11T12:42:15.386993,479392937,786,234,-12.90059138412,24.61394955303,-17.589251951775,2,1,18
+2025-03-11T12:42:15.511993,479392937,786,234,-13.31005926096,25.54257425958,-18.315767622375,2,1,18
+2025-03-11T12:42:15.636993,479392937,786,234,-13.68187491924,26.39727097569,-18.967890578895,2,1,18
+2025-03-11T12:42:15.761993,479392937,786,234,-14.05369057752,27.191947264515,-19.573496026515,2,1,18
+2025-03-11T12:42:15.886993,479392937,786,234,-14.38314748992,27.90807152004,-20.13701505768,2,1,18
+2025-03-11T12:42:16.011993,479392937,786,234,-14.6608326018,28.554863480325,-20.63075526234,2,1,18
+2025-03-11T12:42:16.136993,479392937,786,234,-14.90086549512,29.11849353828,-21.073154670495,2,1,18
+2025-03-11T12:42:16.261993,479392937,786,234,-15.11265922452,29.580508043955,-21.436415620515,2,1,18
+2025-03-11T12:42:16.386993,479392937,786,234,-15.31033337196,29.99171477349,-21.7393168149,2,1,18
+2025-03-11T12:42:16.511993,479392937,786,234,-15.45152919156,30.32434820898,-22.004721146655,2,1,18
+2025-03-11T12:42:16.636993,479392937,786,234,-15.56919237456,30.57845795883,-22.200359110785,2,1,18
+2025-03-11T12:42:16.761993,479392937,786,234,-15.649203339,30.74940580635,-22.321555693335,2,1,18
+2025-03-11T12:42:16.886993,479392937,786,234,-15.6962686122,30.8418157944,-22.396066117875,2,1,18
+2025-03-11T12:42:17.011993,479392937,786,234,-15.68685555756,30.855652488405,-22.39149862665,2,1,18
+2025-03-11T12:42:17.136993,479392937,786,234,-15.64449681168,30.77248349916,-22.3355275254,2,1,18
+2025-03-11T12:42:17.261993,479392937,786,234,-15.5786054292,30.59693995644,-22.209717055275,2,1,18
+2025-03-11T12:42:17.386993,479392937,786,234,-15.47035530084,30.35207829231,-22.02800848515,2,1,18
+2025-03-11T12:42:17.511993,479392937,786,234,-15.32915948124,30.051763548435,-21.781254957705,2,1,18
+2025-03-11T12:42:17.636993,479392937,786,234,-15.14089838844,29.645187948675,-21.473778355515,2,1,18
+2025-03-11T12:42:17.761993,479392937,786,234,-14.92910465904,29.150854751385,-21.091866601185,2,1,18
+2025-03-11T12:42:17.886993,479392937,786,234,-14.68907176572,28.591841649375,-20.66797199484,2,1,18
+2025-03-11T12:42:18.011917,479392941,781,235,-14.41138665384,27.958900556925,-20.1650645574,2,1,18
+2025-03-11T12:42:18.136917,479392941,781,235,-14.11016890536,27.265903602615,-19.601728321365,2,1,18
+2025-03-11T12:42:18.261917,479392941,781,235,-13.766592411,26.475886791225,-18.996208333875,2,1,18
+2025-03-11T12:42:18.386917,479392941,781,235,-13.39477675272,25.61657311917,-18.34868116062,2,1,18
+2025-03-11T12:42:18.511917,479392941,781,235,-12.99472193052,24.69719649834,-17.63147476701,2,1,18
+2025-03-11T12:42:18.636917,479392941,781,235,-12.57113447172,23.71776401565,-16.85845969182,2,1,18
+2025-03-11T12:42:18.761917,479392941,781,235,-12.10518826704,22.664396455605,-16.043382533925,2,1,18
+2025-03-11T12:42:18.886917,479392941,781,235,-11.61100289844,21.560199858675,-15.17253517422,2,1,18
+2025-03-11T12:42:19.011917,479392941,781,235,-11.1074044752,20.38673474874,-14.2689616137,2,1,18
+2025-03-11T12:42:19.136917,479392941,781,235,-10.56144730608,19.15780238523,-13.332663539505,2,1,18
+2025-03-11T12:42:19.261917,479392941,781,235,-10.01078360964,17.8873103313,-12.345314986665,2,1,18
+2025-03-11T12:42:19.386917,479392941,781,235,-9.44129380392,16.593705149985,-11.339323546095,2,1,18
+2025-03-11T12:42:19.511917,479392941,781,235,-8.85768441624,15.24005828064,-10.305264501495,2,1,18
+2025-03-11T12:42:19.636917,479392941,781,235,-8.24583586464,13.82634846252,-9.233867055645,2,1,18
+2025-03-11T12:42:19.761917,479392941,781,235,-7.61045467644,12.39875234199,-8.097664031685,2,1,18
+2025-03-11T12:42:19.886917,479392941,781,235,-6.9656604336,10.938823356015,-6.961270296015,2,1,18
+2025-03-11T12:42:20.011917,479392941,781,235,-6.31615966344,9.4558025034,-5.81088435282,2,1,18
+2025-03-11T12:42:20.136917,479392941,781,235,-5.63371320204,7.949647262655,-4.641824958705,2,1,18
+2025-03-11T12:42:20.261917,479392941,781,235,-4.96067979528,6.40657054818,-3.45411080199,2,1,18
+2025-03-11T12:42:20.386917,479392941,781,235,-4.29235291584,4.86350092062,-2.266406833005,2,1,18
+2025-03-11T12:42:20.511917,479392941,781,235,-3.60519992712,3.3204029454,-1.05094141101,2,1,18
+2025-03-11T12:42:20.636917,479392941,781,235,-2.90863388376,1.744972104735,0.146234254635,2,1,18
+2025-03-11T12:42:20.761917,479392941,781,235,-2.21677436772,0.18339921882,1.357187082345,2,1,18
+2025-03-11T12:42:20.886917,479392941,781,235,-1.53432790632,-1.378159493265,2.58197988564,2,1,18
+2025-03-11T12:42:21.011917,479392941,781,235,-0.84246839028,-2.93973237918,3.78369247932,2,1,18
+2025-03-11T12:42:21.136917,479392941,781,235,-0.16943498352,-4.501276917435,4.96688385402,2,1,18
+2025-03-11T12:42:21.261917,479392941,781,235,0.50359842324,-6.02588580813,6.16836102678,2,1,18
+2025-03-11T12:42:21.386917,479392941,781,235,1.16721877536,-7.532012701215,7.34199978699,2,1,18
+2025-03-11T12:42:21.511917,479392941,781,235,1.81671954552,-9.02426746572,8.492434397685,2,1,18
+2025-03-11T12:42:21.636917,479392941,781,235,2.45680726104,-10.48418936478,9.61495759458,2,1,18
+2025-03-11T12:42:21.761917,479392941,781,235,3.0827753946,-11.897920443645,10.709486188695,2,1,18
+2025-03-11T12:42:21.886917,479392941,781,235,3.70403700084,-13.27932574398,11.7945940248,2,1,18
+2025-03-11T12:42:22.011856,479392945,777,236,4.29235291584,-14.619128832405,12.83783048991,2,1,18
+2025-03-11T12:42:22.136856,479392945,777,236,4.84301661228,-15.92193957795,13.857690198105,2,1,18
+2025-03-11T12:42:22.261856,479392945,777,236,5.39838683604,-17.17858785096,14.84035582041,2,1,18
+2025-03-11T12:42:22.386856,479392945,777,236,5.92081136856,-18.398250868005,15.77193417144,2,1,18
+2025-03-11T12:42:22.511856,479392945,777,236,6.43382284644,-19.5440284161,16.680002221935,2,1,18
+2025-03-11T12:42:22.636856,479392945,777,236,6.92800821504,-20.63899110114,17.52308021205,2,1,18
+2025-03-11T12:42:22.761856,479392945,777,236,7.3892478924,-21.70158548616,18.31509526464,2,1,18
+2025-03-11T12:42:22.886856,479392945,777,236,7.82224840584,-22.68103214268,19.06965024723,2,1,18
+2025-03-11T12:42:23.011856,479392945,777,236,8.22700975536,-23.563480202865,19.76819169051,2,1,18
+2025-03-11T12:42:23.136856,479392945,777,236,8.59411888632,-24.395085052335,20.415562673535,2,1,18
+2025-03-11T12:42:23.261856,479392945,777,236,8.93298885336,-25.15739304114,21.020926470795,2,1,18
+2025-03-11T12:42:23.386856,479392945,777,236,9.2483261838,-25.850411256195,21.53809209987,2,1,18
+2025-03-11T12:42:23.511856,479392945,777,236,9.5071851864,-26.474090089095,22.03166988486,2,1,18
+2025-03-11T12:42:23.636856,479392945,777,236,9.73309849776,-27.01461410658,22.455436593015,2,1,18
+2025-03-11T12:42:23.761856,479392945,777,236,9.9543052818,-27.467408874195,22.81404913398,2,1,18
+2025-03-11T12:42:23.886856,479392945,777,236,10.119033738,-27.86471512749,23.11218589599,2,1,18
+2025-03-11T12:42:24.011856,479392945,777,236,10.24140344832,-28.155767611815,23.368090239045,2,1,18
+2025-03-11T12:42:24.136856,479392945,777,236,10.354360104,-28.38216853908,23.53123119384,2,1,18
+2025-03-11T12:42:24.261856,479392945,777,236,10.41083843184,-28.53923008419,23.638443485445,2,1,18
+2025-03-11T12:42:24.386856,479392945,777,236,10.45319717772,-28.603931249655,23.666596549605,2,1,18
+2025-03-11T12:42:24.511856,479392945,777,236,10.43907759576,-28.56697434135,23.65251096537,2,1,18
+2025-03-11T12:42:24.636856,479392945,777,236,10.4014253772,-28.46534461524,23.5502515467,2,1,18
+2025-03-11T12:42:24.761856,479392945,777,236,10.32612094008,-28.285169942745,23.405915899305,2,1,18
+2025-03-11T12:42:24.886856,479392945,777,236,10.19904470244,-28.031046019065,23.210257559715,2,1,18
+2025-03-11T12:42:25.011856,479392945,777,236,10.04372930088,-27.675306543105,22.93546076199,2,1,18
+2025-03-11T12:42:25.136856,479392945,777,236,9.85076168076,-27.25025603265,22.60939616901,2,1,18
+2025-03-11T12:42:25.261856,479392945,777,236,9.64367447868,-26.746696010385,22.21820570088,2,1,18
+2025-03-11T12:42:25.386856,479392945,777,236,9.37069589412,-26.164548520245,21.766397409585,2,1,18
+2025-03-11T12:42:25.511856,479392945,777,236,9.08830425492,-25.49466469332,21.2586649974,2,1,18
+2025-03-11T12:42:25.636856,479392945,777,236,8.77296692448,-24.77856169854,20.685936295395,2,1,18
+2025-03-11T12:42:25.761856,479392945,777,236,8.42939043012,-23.974694019315,20.05724272158,2,1,18
+2025-03-11T12:42:25.886856,479392945,777,236,8.03404213524,-23.096877088905,19.381846572585,2,1,18
+2025-03-11T12:42:26.011795,479392949,773,237,7.62928078572,-22.15902555738,18.646052188185,2,1,18
+2025-03-11T12:42:26.136795,479392949,773,237,7.177454163,-21.16108272942,17.87749876863,2,1,18
+2025-03-11T12:42:26.261795,479392949,773,237,6.71621448564,-20.08925443251,17.04847411242,2,1,18
+2025-03-11T12:42:26.386795,479392949,773,237,6.22673564436,-18.97121405466,16.177563939195,2,1,18
+2025-03-11T12:42:26.511795,479392949,773,237,5.70901763916,-17.774642904255,15.25073756166,2,1,18
+2025-03-11T12:42:26.636795,479392949,773,237,5.177180052,-16.54573180149,14.30060969961,2,1,18
+2025-03-11T12:42:26.761795,479392949,773,237,4.59357066432,-15.247488403485,13.299183479115,2,1,18
+2025-03-11T12:42:26.886795,479392949,773,237,4.01937433128,-13.94002526742,12.265388147475,2,1,18
+2025-03-11T12:42:27.011795,479392949,773,237,3.42635188896,-12.586364224245,11.203588025325,2,1,18
+2025-03-11T12:42:27.136795,479392949,773,237,2.81450333736,-11.163420494235,10.113661443915,2,1,18
+2025-03-11T12:42:27.261795,479392949,773,237,2.16970909452,-9.71272542015,8.986556609775,2,1,18
+2025-03-11T12:42:27.386795,479392949,773,237,1.53432790632,-8.23895974017,7.850110248315,2,1,18
+2025-03-11T12:42:27.511795,479392949,773,237,0.86600102688,-6.746676628005,6.68115441864,2,1,18
+2025-03-11T12:42:27.636795,479392949,773,237,0.20238067476,-5.22208191114,5.512038440445,2,1,18
+2025-03-11T12:42:27.761795,479392949,773,237,-0.48006578664,-3.669757110945,4.32425524077,2,1,18
+2025-03-11T12:42:27.886795,479392949,773,237,-1.16251224804,-2.11743231075,3.12261169005,2,1,18
+2025-03-11T12:42:28.011795,479392949,773,237,-1.83083912748,-0.57436268319,1.93028760405,2,1,18
+2025-03-11T12:42:28.136795,479392949,773,237,-2.51328558888,0.977962117005,0.71016358527,2,1,18
+2025-03-11T12:42:28.261795,479392949,773,237,-3.2004385776,2.530294004115,-0.505350504225,2,1,18
+2025-03-11T12:42:28.386795,479392949,773,237,-3.89229809364,4.10110080192,-1.71173188242,2,1,18
+2025-03-11T12:42:28.511795,479392949,773,237,-4.5653315004,5.65802838423,-2.908759274415,2,1,18
+2025-03-11T12:42:28.636795,479392949,773,237,-5.24307143448,7.205729141565,-4.11498842067,2,1,18
+2025-03-11T12:42:28.761795,479392949,773,237,-5.91610484124,8.716487164425,-5.293292007105,2,1,18
+2025-03-11T12:42:28.886795,479392949,773,237,-6.57972519336,10.20414623373,-6.45297308127,2,1,18
+2025-03-11T12:42:29.011795,479392949,773,237,-7.24334554548,11.710273126815,-7.594271022375,2,1,18
+2025-03-11T12:42:29.136795,479392949,773,237,-7.87402020636,13.14709607232,-8.721272292075,2,1,18
+2025-03-11T12:42:29.261795,479392949,773,237,-8.49998833992,14.55621019524,-9.801916201395,2,1,18
+2025-03-11T12:42:29.386795,479392949,773,237,-9.10242383688,15.95143801575,-10.85933558574,2,1,18
+2025-03-11T12:42:29.511795,479392949,773,237,-9.68132669724,17.291226930345,-11.879451090315,2,1,18
+2025-03-11T12:42:29.636795,479392949,773,237,-10.25081650296,18.580215155715,-12.89927854818,2,1,18
+2025-03-11T12:42:29.761795,479392949,773,237,-10.78736061744,19.80451638945,-13.863252615255,2,1,18
+2025-03-11T12:42:29.886795,479392949,773,237,-11.30507862264,21.0057044958,-14.79010332654,2,1,18
+2025-03-11T12:42:30.011734,479392953,769,238,-11.80397051856,22.146843827205,-15.670395778005,2,1,18
+2025-03-11T12:42:30.136734,479392953,769,238,-12.27462325056,23.214069342,-16.51327682697,2,1,18
+2025-03-11T12:42:30.261734,479392953,769,238,-12.74056945524,24.239735166375,-17.28662692923,2,1,18
+2025-03-11T12:42:30.386734,479392953,769,238,-13.14533080476,25.191437565735,-18.017874197865,2,1,18
+2025-03-11T12:42:30.511734,479392953,769,238,-13.53597257232,26.083098277065,-18.697953277395,2,1,18
+2025-03-11T12:42:30.636734,479392953,769,238,-13.89366864864,26.88237026109,-19.33589331468,2,1,18
+2025-03-11T12:42:30.761734,479392953,769,238,-14.21841903372,27.60772134159,-19.917931293675,2,1,18
+2025-03-11T12:42:30.886734,479392953,769,238,-14.5196367822,28.3007182959,-20.439686476575,2,1,18
+2025-03-11T12:42:31.011734,479392953,769,238,-14.78790883944,28.882858699125,-20.896104697155,2,1,18
+2025-03-11T12:42:31.136734,479392953,769,238,-15.03264826008,29.409560196435,-21.29211845289,2,1,18
+2025-03-11T12:42:31.261734,479392953,769,238,-15.21620282556,29.848447400895,-21.641336256735,2,1,18
+2025-03-11T12:42:31.386734,479392953,769,238,-15.35739864516,30.23186735178,-21.93472896183,2,1,18
+2025-03-11T12:42:31.511734,479392953,769,238,-15.4844748828,30.509076055185,-22.1397492042,2,1,18
+2025-03-11T12:42:31.636734,479392953,769,238,-15.59272501116,30.71238511581,-22.293518068485,2,1,18
+2025-03-11T12:42:31.761734,479392953,769,238,-15.649203339,30.837127969305,-22.40056002384,2,1,18
+2025-03-11T12:42:31.886734,479392953,769,238,-15.66802944828,30.86024109669,-22.40072244351,2,1,18
+2025-03-11T12:42:32.011734,479392953,769,238,-15.649203339,30.80480927769,-22.368048868485,2,1,18
+2025-03-11T12:42:32.136734,479392953,769,238,-15.59272501116,30.68468338014,-22.284131831955,2,1,18
+2025-03-11T12:42:32.261734,479392953,769,238,-15.51742057404,30.476806971975,-22.116549596985,2,1,18
+2025-03-11T12:42:32.386734,479392953,769,238,-15.37622475444,30.181109184045,-21.883680754335,2,1,18
+2025-03-11T12:42:32.511734,479392953,769,238,-15.2256158802,29.81614288311,-21.60884547684,2,1,18
+2025-03-11T12:42:32.636734,479392953,769,238,-15.03264826008,29.35877368104,-21.23640937746,2,1,18
+2025-03-11T12:42:32.761734,479392953,769,238,-14.79732189408,28.81361853378,-20.8449387792,2,1,18
+2025-03-11T12:42:32.886734,479392953,769,238,-14.52434330952,28.217620175805,-20.36071666755,2,1,18
+2025-03-11T12:42:33.011734,479392953,769,238,-14.22312556104,27.524623221495,-19.84820171868,2,1,18
+2025-03-11T12:42:33.136734,479392953,769,238,-13.89837517596,26.78542127316,-19.266090738435,2,1,18
+2025-03-11T12:42:33.261734,479392953,769,238,-13.531266045,25.949199467745,-18.632555772705,2,1,18
+2025-03-11T12:42:33.386734,479392953,769,238,-13.1312112228,25.066758494475,-17.93864463417,2,1,18
+2025-03-11T12:42:33.511734,479392953,769,238,-12.71233029132,24.10580092248,-17.179597432755,2,1,18
+2025-03-11T12:42:33.636734,479392953,769,238,-12.26521019592,23.07554648982,-16.387783279605,2,1,18
+2025-03-11T12:42:33.761734,479392953,769,238,-11.78514440928,21.989838977415,-15.55402475421,2,1,18
+2025-03-11T12:42:33.886734,479392953,769,238,-11.30037209532,20.84410395081,-14.66911841517,2,1,18
+2025-03-11T12:42:34.011657,479392957,764,239,-10.77324103548,19.64290167063,-13.73762721141,2,1,18
+2025-03-11T12:42:34.136657,479392957,764,239,-10.236696921,18.40474956906,-12.764339909055,2,1,18
+2025-03-11T12:42:34.261657,479392957,764,239,-9.6719136426,17.106534518715,-11.76295443948,2,1,18
+2025-03-11T12:42:34.386657,479392957,764,239,-9.06947814564,15.78056103738,-10.724380529445,2,1,18
+2025-03-11T12:42:34.511657,479392957,764,239,-8.46233612136,14.39917699779,-9.671644075635,2,1,18
+2025-03-11T12:42:34.636657,479392957,764,239,-7.84107451512,12.971602138005,-8.563192316955,2,1,18
+2025-03-11T12:42:34.761657,479392957,764,239,-7.21510638156,11.525552367525,-7.43153245047,2,1,18
+2025-03-11T12:42:34.886657,479392957,764,239,-6.5656056114,10.03329760302,-6.28571795679,2,1,18
+2025-03-11T12:42:35.011657,479392957,764,239,-5.89727873196,8.531780578965,-5.1120933426,2,1,18
+2025-03-11T12:42:35.136657,479392957,764,239,-5.22895185252,7.01179573113,-3.942991510425,2,1,18
+2025-03-11T12:42:35.261657,479392957,764,239,-4.56062497308,5.464109147625,-2.759883324705,2,1,18
+2025-03-11T12:42:35.386657,479392957,764,239,-3.87817851168,3.92101825932,-1.549048207455,2,1,18
+2025-03-11T12:42:35.511657,479392957,764,239,-3.18161246832,2.364055242435,-0.347349759795,2,1,18
+2025-03-11T12:42:35.636657,479392957,764,239,-2.49916600692,0.788645662515,0.86827581072,2,1,18
+2025-03-11T12:42:35.761657,479392957,764,239,-1.80259996356,-0.772934310315,2.083858943175,2,1,18
+2025-03-11T12:42:35.886657,479392957,764,239,-1.11544697484,-2.31141532959,3.29005979739,2,1,18
+2025-03-11T12:42:36.011657,479392957,764,239,-0.45653315004,-3.83600295954,4.496126523975,2,1,18
+2025-03-11T12:42:36.136657,479392957,764,239,0.19296762012,-5.38827815133,5.66535794148,2,1,18
+2025-03-11T12:42:36.261657,479392957,764,239,0.86600102688,-6.931354865805,6.853072098195,2,1,18
+2025-03-11T12:42:36.386657,479392957,764,239,1.53903443364,-8.43749593272,8.01287088282,2,1,18
+2025-03-11T12:42:36.511657,479392957,764,239,2.19794825844,-9.89744617944,9.153915298695,2,1,18
+2025-03-11T12:42:36.636657,479392957,764,239,2.81920986468,-11.32963799517,10.26701150814,2,1,18
+2025-03-11T12:42:36.761657,479392957,764,239,3.4357649436,-12.72950403237,11.36606684256,2,1,18
+2025-03-11T12:42:36.886657,479392957,764,239,4.03820044056,-14.09703011721,12.40947987336,2,1,18
+2025-03-11T12:42:37.011657,479392957,764,239,4.63122288288,-15.41837246877,13.429528606125,2,1,18
+2025-03-11T12:42:37.136657,479392957,764,239,5.177180052,-16.698091347675,14.426155872765,2,1,18
+2025-03-11T12:42:37.261657,479392957,764,239,5.72313722112,-17.92240675524,15.385530198285,2,1,18
+2025-03-11T12:42:37.386657,479392957,764,239,6.25497480828,-19.09129743072,16.298380785465,2,1,18
+2025-03-11T12:42:37.511657,479392957,764,239,6.74445364956,-20.204720852625,17.15078615688,2,1,18
+2025-03-11T12:42:37.636657,479392957,764,239,7.2009867996,-21.262691194785,17.956627039035,2,1,18
+2025-03-11T12:42:37.761657,479392957,764,239,7.63398731304,-22.27445654292,18.729832825935,2,1,18
+2025-03-11T12:42:37.886657,479392957,764,239,8.04345518988,-23.22154907325,19.456445831535,2,1,18
+2025-03-11T12:42:38.011596,479392961,760,240,8.43880348476,-24.09936600366,20.14108221456,2,1,18
+2025-03-11T12:42:38.136596,479392961,760,240,8.79179303376,-24.89863090077,20.769771830085,2,1,18
+2025-03-11T12:42:38.261596,479392961,760,240,9.11183689152,-25.614740982465,21.31479001773,2,1,18
+2025-03-11T12:42:38.386596,479392961,760,240,9.39893505804,-26.25231320469,21.82698239841,2,1,18
+2025-03-11T12:42:38.511596,479392961,760,240,9.66250058796,-26.829829565055,22.26488562945,2,1,18
+2025-03-11T12:42:38.636596,479392961,760,240,9.86958779004,-27.30568785165,22.64668986105,2,1,18
+2025-03-11T12:42:38.761596,479392961,760,240,10.06726193748,-27.7492132728,22.98210221079,2,1,18
+2025-03-11T12:42:38.886596,479392961,760,240,10.19904470244,-28.10953427013,23.238391935555,2,1,18
+2025-03-11T12:42:39.011596,479392961,760,240,10.31670788544,-28.3451761962,23.4385526817,2,1,18
+2025-03-11T12:42:39.136596,479392961,760,240,10.4014253772,-28.5022802628,23.56892668476,2,1,18
+2025-03-11T12:42:39.261596,479392961,760,240,10.43437106844,-28.59928594605,23.63419064583,2,1,18
+2025-03-11T12:42:39.386596,479392961,760,240,10.44378412308,-28.62700185555,23.64359725782,2,1,18
+2025-03-11T12:42:39.511596,479392961,760,240,10.42025148648,-28.571562949635,23.601673261035,2,1,18
+2025-03-11T12:42:39.636596,479392961,760,240,10.34965357668,-28.42371405567,23.489858956725,2,1,18
+2025-03-11T12:42:39.761596,479392961,760,240,10.25081650296,-28.1511648297,23.303404642545,2,1,18
+2025-03-11T12:42:39.886596,479392961,760,240,10.10962068336,-27.832382262045,23.061173897115,2,1,18
+2025-03-11T12:42:40.011596,479392961,760,240,9.92606611788,-27.439664617035,22.735300015845,2,1,18
+2025-03-11T12:42:40.136596,479392961,760,240,9.72839197044,-26.977671372105,22.37668974603,2,1,18
+2025-03-11T12:42:40.261596,479392961,760,240,9.47423949516,-26.41863700935,21.952764576495,2,1,18
+2025-03-11T12:42:40.386596,479392961,760,240,9.21538049256,-25.781107308615,21.44525343921,2,1,18
+2025-03-11T12:42:40.511596,479392961,760,240,8.90004316212,-25.074238225725,20.91415445784,2,1,18
+2025-03-11T12:42:40.636596,479392961,760,240,8.56117319508,-24.30269632503,20.29026152502,2,1,18
+2025-03-11T12:42:40.761596,479392961,760,240,8.19406406412,-23.46185756367,19.642841874495,2,1,18
+2025-03-11T12:42:40.886596,479392961,760,240,7.79871576924,-22.542488029755,18.944126136675,2,1,18
+2025-03-11T12:42:41.011596,479392961,760,240,7.37042178312,-21.57228237204,18.180389775285,2,1,18
+2025-03-11T12:42:41.136596,479392961,760,240,6.92800821504,-20.523567202515,17.351527538745,2,1,18
+2025-03-11T12:42:41.261596,479392961,760,240,6.42911631912,-19.423980474615,16.50841502715,2,1,18
+2025-03-11T12:42:41.386596,479392961,760,240,5.91610484124,-18.264352058685,15.609514209435,2,1,18
+2025-03-11T12:42:41.511596,479392961,760,240,5.38426725408,-17.03544095592,14.67324669843,2,1,18
+2025-03-11T12:42:41.636596,479392961,760,240,4.8477231396,-15.77882103057,13.68600171003,2,1,18
+2025-03-11T12:42:41.761596,479392961,760,240,4.2594072246,-14.46210272187,12.675227732775,2,1,18
+2025-03-11T12:42:41.886596,479392961,760,240,3.6710913096,-13.12691658939,11.6273954844,2,1,18
+2025-03-11T12:42:42.011535,479392965,756,241,3.06865581264,-11.745539636715,10.56542898429,2,1,18
+2025-03-11T12:42:42.136535,479392965,756,241,2.44268767908,-10.30410682218,9.452273919615,2,1,18
+2025-03-11T12:42:42.261535,479392965,756,241,1.79789343624,-8.844177836205,8.31126006693,2,1,18
+2025-03-11T12:42:42.386535,479392965,756,241,1.14839266608,-7.356540027645,7.151609555955,2,1,18
+2025-03-11T12:42:42.511535,479392965,756,241,0.48006578664,-5.86425691548,6.00113419434,2,1,18
+2025-03-11T12:42:42.636535,479392965,756,241,-0.1882610928,-4.32118728792,4.80881010834,2,1,18
+2025-03-11T12:42:42.761535,479392965,756,241,-0.85188144492,-2.77350779133,3.602611525275,2,1,18
+2025-03-11T12:42:42.886535,479392965,756,241,-1.55786054292,-1.22114755656,2.410157269935,2,1,18
+2025-03-11T12:42:43.011535,479392965,756,241,-2.23089394968,0.36348176142,1.199123524395,2,1,18
+2025-03-11T12:42:43.136535,479392965,756,241,-2.90863388376,1.911182518755,-0.00710562186,2,1,18
+2025-03-11T12:42:43.261535,479392965,756,241,-3.6004933998,3.47275540467,-1.21805844957,2,1,18
+2025-03-11T12:42:43.386535,479392965,756,241,-4.29235291584,5.025094378695,-2.424342492765,2,1,18
+2025-03-11T12:42:43.511535,479392965,756,241,-4.95597326796,6.572773875285,-3.616680724785,2,1,18
+2025-03-11T12:42:43.636535,479392965,756,241,-5.63371320204,8.12047463262,-4.81366963701,2,1,18
+2025-03-11T12:42:43.761535,479392965,756,241,-6.29733355416,9.63121848165,-5.982712613955,2,1,18
+2025-03-11T12:42:43.886535,479392965,756,241,-6.95624737896,11.114253508095,-7.128498815595,2,1,18
+2025-03-11T12:42:44.011535,479392965,756,241,-7.59162856716,12.560317452405,-8.25093882351,2,1,18
+2025-03-11T12:42:44.136535,479392965,756,241,-8.23171628268,14.001771527685,-9.35026410033,2,1,18
+2025-03-11T12:42:44.261535,479392965,756,241,-8.83885830696,15.38777252322,-10.426125472965,2,1,18
+2025-03-11T12:42:44.386535,479392965,756,241,-9.41776116732,16.73217839376,-11.478606130395,2,1,18
+2025-03-11T12:42:44.511535,479392965,756,241,-9.99195750036,18.03502457388,-12.49851677724,2,1,18
+2025-03-11T12:42:44.636535,479392965,756,241,-10.57086036072,19.310176105245,-13.47671055618,2,1,18
+2025-03-11T12:42:44.761535,479392965,756,241,-11.09799142056,20.53446316515,-14.41756366272,2,1,18
+2025-03-11T12:42:44.886535,479392965,756,241,-11.6015898438,21.698694363195,-15.316468438725,2,1,18
+2025-03-11T12:42:45.011535,479392965,756,241,-12.09106868508,22.79364996132,-16.154916124095,2,1,18
+2025-03-11T12:42:45.136535,479392965,756,241,-12.5664279444,23.84241473925,-16.9699893237,2,1,18
+2025-03-11T12:42:45.261535,479392965,756,241,-12.99472193052,24.80800344102,-17.729081234325,2,1,18
+2025-03-11T12:42:45.386535,479392965,756,241,-13.40418980736,25.7089264119,-18.41386984929,2,1,18
+2025-03-11T12:42:45.511535,479392965,756,241,-13.78071199296,26.554396303035,-19.06595432604,2,1,18
+2025-03-11T12:42:45.636535,479392965,756,241,-14.11016890536,27.33515794179,-19.694495667915,2,1,18
+2025-03-11T12:42:45.761535,479392965,756,241,-14.40668012652,28.02353085324,-20.23931691441,2,1,18
+2025-03-11T12:42:45.886535,479392965,756,241,-14.69848482036,28.66111016238,-20.73303901476,2,1,18
+2025-03-11T12:42:46.011474,479392969,752,242,-14.93851771368,29.215506308445,-21.1707696384,2,1,18
+2025-03-11T12:42:46.136474,479392969,752,242,-15.14560491576,29.70059850693,-21.529521952425,2,1,18
+2025-03-11T12:42:46.261474,479392969,752,242,-15.3197464266,30.107152845945,-21.809247289335,2,1,18
+2025-03-11T12:42:46.386474,479392969,752,242,-15.45623571888,30.416694414795,-22.060659413565,2,1,18
+2025-03-11T12:42:46.511474,479392969,752,242,-15.55977931992,30.65231508012,-22.24230912846,2,1,18
+2025-03-11T12:42:46.636474,479392969,752,242,-15.6256707024,30.80015688717,-22.35411324504,2,1,18
+2025-03-11T12:42:46.761474,479392969,752,242,-15.68214903024,30.869496269325,-22.41004190823,2,1,18
+2025-03-11T12:42:46.886474,479392969,752,242,-15.66802944828,30.837156316965,-22.40984100879,2,1,18
+2025-03-11T12:42:47.011474,479392969,752,242,-15.62096417508,30.72166154919,-22.339829032515,2,1,18
+2025-03-11T12:42:47.136474,479392969,752,242,-15.53624668332,30.550706614755,-22.200141794175,2,1,18
+2025-03-11T12:42:47.261474,479392969,752,242,-15.43270308228,30.310468993485,-21.99074704344,2,1,18
+2025-03-11T12:42:47.386474,479392969,752,242,-15.28209420804,29.968587472275,-21.743754136785,2,1,18
+2025-03-11T12:42:47.511474,479392969,752,242,-15.11265922452,29.54818935234,-21.399284348145,2,1,18
+2025-03-11T12:42:47.636474,479392969,752,242,-14.90557202244,29.072331065745,-21.01285999953,2,1,18
+2025-03-11T12:42:47.761474,479392969,752,242,-14.6372999652,28.485573706575,-20.579518030275,2,1,18
+2025-03-11T12:42:47.886474,479392969,752,242,-14.34549527136,27.84337744149,-20.076531362145,2,1,18
+2025-03-11T12:42:48.011474,479392969,752,242,-14.03486446824,27.127281533625,-19.5130530819,2,1,18
+2025-03-11T12:42:48.136474,479392969,752,242,-13.68187491924,26.32339968057,-18.893579366655,2,1,18
+2025-03-11T12:42:48.261474,479392969,752,242,-13.295939679,25.440979968045,-18.222799376385,2,1,18
+2025-03-11T12:42:48.386474,479392969,752,242,-12.90529791144,24.512383609155,-17.514804924765,2,1,18
+2025-03-11T12:42:48.511474,479392969,752,242,-12.47700392532,23.53294403955,-16.732539427815,2,1,18
+2025-03-11T12:42:48.636474,479392969,752,242,-12.001644666,22.46571143784,-15.903508542165,2,1,18
+2025-03-11T12:42:48.761474,479392969,752,242,-11.51216582472,21.32920323621,-15.037121150955,2,1,18
+2025-03-11T12:42:48.886474,479392969,752,242,-11.00386087416,20.16496495125,-14.13820618722,2,1,18
+2025-03-11T12:42:49.011474,479392969,752,242,-10.45319717772,18.926791588935,-13.174128555705,2,1,18
+2025-03-11T12:42:49.136474,479392969,752,242,-9.89782695396,17.66552635998,-12.205298950695,2,1,18
+2025-03-11T12:42:49.261474,479392969,752,242,-9.32833714824,16.33036857516,-11.171367804285,2,1,18
+2025-03-11T12:42:49.386474,479392969,752,242,-8.72119512396,14.953601491515,-10.109415450195,2,1,18
+2025-03-11T12:42:49.511474,479392969,752,242,-8.11405309968,13.535281804365,-9.00566303922,2,1,18
+2025-03-11T12:42:49.636474,479392969,752,242,-7.45513927488,12.10765024926,-7.883269427655,2,1,18
+2025-03-11T12:42:49.761474,479392969,752,242,-6.81975808668,10.656969349005,-6.756184968975,2,1,18
+2025-03-11T12:42:49.886474,479392969,752,242,-6.1655507892,9.146239673805,-5.591782484505,2,1,18
+2025-03-11T12:42:50.011413,479392973,748,243,-5.49251738244,7.64009860689,-4.418123348835,2,1,18
+2025-03-11T12:42:50.136413,479392973,748,243,-4.82889703032,6.11088693408,-3.23050256883,2,1,18
+2025-03-11T12:42:50.261413,479392973,748,243,-4.16057015088,4.563200350575,-2.033534032065,2,1,18
+2025-03-11T12:42:50.386413,479392973,748,243,-3.4828302168,2.983180901625,-0.8086540815,2,1,18
+2025-03-11T12:42:50.511413,479392973,748,243,-2.79567722808,1.412381190735,0.39309699195,2,1,18
+2025-03-11T12:42:50.636413,479392973,748,243,-2.09911118472,-0.13534791426,1.60398700614,2,1,18
+2025-03-11T12:42:50.761413,479392973,748,243,-1.40254514136,-1.71539571087,2.819667473595,2,1,18
+2025-03-11T12:42:50.886413,479392973,748,243,-0.71539215264,-3.253876730145,4.030488444825,2,1,18
+2025-03-11T12:42:51.011413,479392973,748,243,-0.03294569124,-4.792350662505,5.222818760265,2,1,18
+2025-03-11T12:42:51.136413,479392973,748,243,0.62596813356,-6.316938292455,6.387304433715,2,1,18
+2025-03-11T12:42:51.261413,479392973,748,243,1.28958848568,-7.818448229595,7.542438392115,2,1,18
+2025-03-11T12:42:51.386413,479392973,748,243,1.95791536512,-9.31073134176,8.688293636715,2,1,18
+2025-03-11T12:42:51.511413,479392973,748,243,2.60270960796,-10.77527728368,9.80161112106,2,1,18
+2025-03-11T12:42:51.636413,479392973,748,243,3.2239712142,-12.193618231575,10.90077397821,2,1,18
+2025-03-11T12:42:51.761413,479392973,748,243,3.82170018384,-13.57037114139,11.97194619087,2,1,18
+2025-03-11T12:42:51.886413,479392973,748,243,4.39118998956,-14.89629501432,13.019689020825,2,1,18
+2025-03-11T12:42:52.011413,479392973,748,243,4.95597326796,-16.18989310872,14.025670273665,2,1,18
+2025-03-11T12:42:52.136413,479392973,748,243,5.5066369644,-17.428066471035,14.98974790518,2,1,18
+2025-03-11T12:42:52.261413,479392973,748,243,6.03376802424,-18.638502663105,15.916667659425,2,1,18
+2025-03-11T12:42:52.386413,479392973,748,243,6.5420729748,-19.77965616834,16.80622072038,2,1,18
+2025-03-11T12:42:52.511413,479392973,748,243,7.02684528876,-20.851519899825,17.639916432255,2,1,18
+2025-03-11T12:42:52.636413,479392973,748,243,7.4833784388,-21.891022418205,18.42717951135,2,1,18
+2025-03-11T12:42:52.761413,479392973,748,243,7.92108547956,-22.847391381915,19.177002895905,2,1,18
+2025-03-11T12:42:52.886413,479392973,748,243,8.30231419248,-23.73442096347,19.87089761727,2,1,18
+2025-03-11T12:42:53.011413,479392973,748,243,8.64589068684,-24.55213951053,20.508904426365,2,1,18
+2025-03-11T12:42:53.136413,479392973,748,243,8.99417370852,-25.305227761275,21.09113934651,2,1,18
+2025-03-11T12:42:53.261413,479392973,748,243,9.28597840236,-25.979742717975,21.61277681895,2,1,18
+2025-03-11T12:42:53.386413,479392973,748,243,9.54954393228,-26.57572690212,22.083118204095,2,1,18
+2025-03-11T12:42:53.511413,479392973,748,243,9.7895768256,-27.10703826846,22.502246690925,2,1,18
+2025-03-11T12:42:53.636413,479392973,748,243,9.98254444572,-27.587492250255,22.86094410801,2,1,18
+2025-03-11T12:42:53.761413,479392973,748,243,10.12844679264,-27.94783450833,23.163465566115,2,1,18
+2025-03-11T12:42:53.886413,479392973,748,243,10.26964261224,-28.23429838437,23.37318515619,2,1,18
+2025-03-11T12:42:54.011337,479392977,743,244,10.38259926792,-28.451465399745,23.527037209455,2,1,18
+2025-03-11T12:42:54.136337,479392977,743,244,10.43907759576,-28.571591297295,23.629434714045,2,1,18
+2025-03-11T12:42:54.261337,479392977,743,244,10.45319717772,-28.622399073435,23.675934118635,2,1,18
+2025-03-11T12:42:54.386337,479392977,743,244,10.44378412308,-28.576215340155,23.64332958657,2,1,18
+2025-03-11T12:42:54.511337,479392977,743,244,10.38259926792,-28.460699311635,23.545566345015,2,1,18
+2025-03-11T12:42:54.636337,479392977,743,244,10.3072948308,-28.26205681536,23.368792543515,2,1,18
+2025-03-11T12:42:54.761337,479392977,743,244,10.1896316478,-27.975628373895,23.145263541045,2,1,18
+2025-03-11T12:42:54.886337,479392977,743,244,10.02960971892,-27.624498766965,22.87048088934,2,1,18
+2025-03-11T12:42:55.011337,479392977,743,244,9.82722904416,-27.185583214845,22.530462568605,2,1,18
+2025-03-11T12:42:55.136337,479392977,743,244,9.60602226012,-26.64968324022,22.120590732975,2,1,18
+2025-03-11T12:42:55.261337,479392977,743,244,9.3424567302,-26.05831601202,21.65951391561,2,1,18
+2025-03-11T12:42:55.386337,479392977,743,244,9.05065203636,-25.388418011265,21.133280659905,2,1,18
+2025-03-11T12:42:55.511337,479392977,743,244,8.72119512396,-24.65382593196,20.546563708665,2,1,18
+2025-03-11T12:42:55.636337,479392977,743,244,8.36820557496,-23.831476255125,19.90851219036,2,1,18
+2025-03-11T12:42:55.761337,479392977,743,244,7.96815075276,-22.94441832591,19.22843706912,2,1,18
+2025-03-11T12:42:55.886337,479392977,743,244,7.5539763486,-21.97423392894,18.50169220704,2,1,18
+2025-03-11T12:42:56.011337,479392977,743,244,7.1068562532,-20.948596452225,17.714522504655,2,1,18
+2025-03-11T12:42:56.136337,479392977,743,244,6.62679046656,-19.89059067549,16.876289864745,2,1,18
+2025-03-11T12:42:56.261337,479392977,743,244,6.13731162528,-18.75408247386,15.98680188846,2,1,18
+2025-03-11T12:42:56.386337,479392977,743,244,5.62900667472,-17.566759409175,15.07390490493,2,1,18
+2025-03-11T12:42:56.511337,479392977,743,244,5.06422339632,-16.319330874225,14.10512792571,2,1,18
+2025-03-11T12:42:56.636337,479392977,743,244,4.50414664524,-15.030356822685,13.113041545395,2,1,18
+2025-03-11T12:42:56.761337,479392977,743,244,3.91583073024,-13.69978764615,12.088334215845,2,1,18
+2025-03-11T12:42:56.886337,479392977,743,244,3.31339523328,-12.318410693475,11.017127481705,2,1,18
+2025-03-11T12:42:57.011337,479392977,743,244,2.69684015436,-10.900076832495,9.9225949293,2,1,18
+2025-03-11T12:42:57.136337,479392977,743,244,2.05675243884,-9.44477188938,8.781615598095,2,1,18
+2025-03-11T12:42:57.261337,479392977,743,244,1.41666472332,-7.952531298705,7.63120136286,2,1,18
+2025-03-11T12:42:57.386337,479392977,743,244,0.74363131656,-6.44639023179,6.47602269525,2,1,18
+2025-03-11T12:42:57.511337,479392977,743,244,0.0705979098,-4.940249164875,5.29312332555,2,1,18
+2025-03-11T12:42:57.636337,479392977,743,244,-0.59302244232,-3.40642053612,4.11009832881,2,1,18
+2025-03-11T12:42:57.761337,479392977,743,244,-1.28958848568,-1.85407447518,2.91766444893,2,1,18
+2025-03-11T12:42:57.886337,479392977,743,244,-1.98144800172,-0.292501589265,1.711331738235,2,1,18
+2025-03-11T12:42:58.011276,479392981,739,245,-2.65448140848,1.26904294899,0.4865593104,2,1,18
+2025-03-11T12:42:58.136276,479392981,739,245,-3.32751481524,2.83520444319,-0.738237451185,2,1,18
+2025-03-11T12:42:58.261276,479392981,739,245,-4.01937433128,4.396777329105,-1.939950044865,2,1,18
+2025-03-11T12:42:58.386276,479392981,739,245,-4.70652732,5.95372617216,-3.12776776602,2,1,18
+2025-03-11T12:42:58.511276,479392981,739,245,-5.39368030872,7.482973279545,-4.333919952735,2,1,18
+2025-03-11T12:42:58.636276,479392981,739,245,-6.04318107888,8.97522804405,-5.50283503149,2,1,18
+2025-03-11T12:42:58.761276,479392981,739,245,-6.69268184904,10.49980150017,-6.671920446495,2,1,18
+2025-03-11T12:42:58.886276,479392981,739,245,-7.33747609188,11.959730486145,-7.81293429918,2,1,18
+2025-03-11T12:42:59.011276,479392981,739,245,-7.96815075276,13.40578734354,-8.926123885335,2,1,18
+2025-03-11T12:42:59.136276,479392981,739,245,-8.59411888632,14.80566755457,-10.025199595215,2,1,18
+2025-03-11T12:42:59.261276,479392981,739,245,-9.19655438328,16.177810595355,-11.077877193795,2,1,18
+2025-03-11T12:42:59.386276,479392981,739,245,-9.7895768256,17.51300381475,-12.102619044825,2,1,18
+2025-03-11T12:42:59.511276,479392981,739,245,-10.34494704936,18.801970779375,-13.090075120395,2,1,18
+2025-03-11T12:42:59.636276,479392981,739,245,-10.8956107458,20.0309102298,-14.04486385038,2,1,18
+2025-03-11T12:42:59.761276,479392981,739,245,-11.413328751,21.21363051237,-14.97623734368,2,1,18
+2025-03-11T12:42:59.886276,479392981,739,245,-11.91692717424,22.340926062855,-15.847226747595,2,1,18
+2025-03-11T12:43:00.011276,479392981,739,245,-12.39699296088,23.41739966337,-16.66245613743,2,1,18
+2025-03-11T12:43:00.136276,479392981,739,245,-12.825286947,24.4199240127,-17.458703654175,2,1,18
+2025-03-11T12:43:00.261276,479392981,739,245,-13.23004829652,25.35315858828,-18.185233470795,2,1,18
+2025-03-11T12:43:00.386276,479392981,739,245,-13.6253965914,26.217124650855,-18.855936501525,2,1,18
+2025-03-11T12:43:00.511276,479392981,739,245,-13.97367961308,27.020999416995,-19.47540002904,2,1,18
+2025-03-11T12:43:00.636276,479392981,739,245,-14.29372347084,27.760194278415,-20.04364047051,2,1,18
+2025-03-11T12:43:00.761276,479392981,739,245,-14.57611511004,28.425461149395,-20.54672843193,2,1,18
+2025-03-11T12:43:00.886276,479392981,739,245,-14.83497411264,29.012204334735,-21.0031506108,2,1,18
+2025-03-11T12:43:01.011276,479392981,739,245,-15.07030047864,29.511189922545,-21.408238222605,2,1,18
+2025-03-11T12:43:01.136276,479392981,739,245,-15.26797462608,29.936247519915,-21.734313003315,2,1,18
+2025-03-11T12:43:01.261276,479392981,739,245,-15.42329002764,30.28737003993,-21.99984523326,2,1,18
+2025-03-11T12:43:01.386276,479392981,739,245,-15.53624668332,30.54608965881,-22.200117460425,2,1,18
+2025-03-11T12:43:01.511276,479392981,739,245,-15.6021380658,30.72163320153,-22.339788281595,2,1,18
+2025-03-11T12:43:01.636276,479392981,739,245,-15.66802944828,30.83253936102,-22.432917260115,2,1,18
+2025-03-11T12:43:01.761276,479392981,739,245,-15.68685555756,30.85103553246,-22.43767546305,2,1,18
+2025-03-11T12:43:01.886276,479392981,739,245,-15.66332292096,30.7909796706,-22.3911070155,2,1,18
+2025-03-11T12:43:02.011215,479392985,735,246,-15.61155112044,30.633925212405,-22.293145145655,2,1,18
+2025-03-11T12:43:02.136215,479392985,735,246,-15.5080075194,30.41677237086,-22.106972648745,2,1,18
+2025-03-11T12:43:02.261215,479392985,735,246,-15.3668116998,30.097989803205,-21.864741903315,2,1,18
+2025-03-11T12:43:02.386215,479392985,735,246,-15.20678977092,29.728392372495,-21.55290098049,2,1,18
+2025-03-11T12:43:02.511215,479392985,735,246,-14.98558298688,29.252512825155,-21.184926536745,2,1,18
+2025-03-11T12:43:02.636215,479392985,735,246,-14.7549631482,28.702747808865,-20.77958144142,2,1,18
+2025-03-11T12:43:02.761215,479392985,735,246,-14.472571509,28.083650497335,-20.30445751959,2,1,18
+2025-03-11T12:43:02.886215,479392985,735,246,-14.16194070588,27.381405457305,-19.750292474625,2,1,18
+2025-03-11T12:43:03.011215,479392985,735,246,-13.8371903208,26.64220350897,-19.154321143335,2,1,18
+2025-03-11T12:43:03.136215,479392985,735,246,-13.47949424448,25.815229789275,-18.51623510355,2,1,18
+2025-03-11T12:43:03.261215,479392985,735,246,-13.07943942228,24.90047012439,-17.812913394735,2,1,18
+2025-03-11T12:43:03.386215,479392985,735,246,-12.6370258542,23.91177538215,-17.058289369185,2,1,18
+2025-03-11T12:43:03.511215,479392985,735,246,-12.18519923148,22.87689690663,-16.25258034351,2,1,18
+2025-03-11T12:43:03.636215,479392985,735,246,-11.70983997216,21.786579525195,-15.391086970005,2,1,18
+2025-03-11T12:43:03.761215,479392985,735,246,-11.20624154892,20.64081615093,-14.496899646015,2,1,18
+2025-03-11T12:43:03.886215,479392985,735,246,-10.67911048908,19.43037995886,-13.56073965774,2,1,18
+2025-03-11T12:43:04.011215,479392985,735,246,-10.12844679264,18.15988790493,-12.587251455945,2,1,18
+2025-03-11T12:43:04.136215,479392985,735,246,-9.56366351424,16.84782198675,-11.581172868105,2,1,18
+2025-03-11T12:43:04.261215,479392985,735,246,-8.95652148996,15.498756638775,-10.547087218605,2,1,18
+2025-03-11T12:43:04.386215,479392985,735,246,-8.36349904764,14.1450955956,-9.476046862425,2,1,18
+2025-03-11T12:43:04.511215,479392985,735,246,-7.75165049604,12.70368404181,-8.367542477955,2,1,18
+2025-03-11T12:43:04.636215,479392985,735,246,-7.10214972588,11.248364924865,-7.25426347338,2,1,18
+2025-03-11T12:43:04.761215,479392985,735,246,-6.43852937376,9.765322811505,-6.11770731804,2,1,18
+2025-03-11T12:43:04.886215,479392985,735,246,-5.77961554896,8.249969093445,-4.95327031209,2,1,18
+2025-03-11T12:43:05.011215,479392985,735,246,-5.1065821422,6.72536020275,-3.77027360739,2,1,18
+2025-03-11T12:43:05.136215,479392985,735,246,-4.41942915348,5.177645271585,-2.564024085675,2,1,18
+2025-03-11T12:43:05.261215,479392985,735,246,-3.73698269208,3.62532047139,-1.371620768985,2,1,18
+2025-03-11T12:43:05.386215,479392985,735,246,-3.059242758,2.06376884622,-0.160698504465,2,1,18
+2025-03-11T12:43:05.511215,479392985,735,246,-2.3767962966,0.502210134135,1.06409429883,2,1,18
+2025-03-11T12:43:05.636215,479392985,735,246,-1.69905636252,-1.05472453509,2.28423246363,2,1,18
+2025-03-11T12:43:05.761215,479392985,735,246,-0.99778379184,-2.625545506725,3.50449456833,2,1,18
+2025-03-11T12:43:05.886215,479392985,735,246,-0.31063080312,-4.19172826167,4.71546154206,2,1,18
+2025-03-11T12:43:06.011154,479392989,731,247,0.35769607632,-5.71633006545,5.889207825,2,1,18
+2025-03-11T12:43:06.136154,479392989,731,247,1.02131642844,-7.21784000259,7.058202134445,2,1,18
+2025-03-11T12:43:06.261154,479392989,731,247,1.6708171986,-8.710094767095,8.213256862155,2,1,18
+2025-03-11T12:43:06.386154,479392989,731,247,2.31561144144,-10.174640709015,9.34505481456,2,1,18
+2025-03-11T12:43:06.511154,479392989,731,247,2.93687304768,-11.62068339258,10.45360390824,2,1,18
+2025-03-11T12:43:06.636154,479392989,731,247,3.5534281266,-13.015932473835,11.52491420682,2,1,18
+2025-03-11T12:43:06.761154,479392989,731,247,4.13703751428,-14.36957934318,12.582073836495,2,1,18
+2025-03-11T12:43:06.886154,479392989,731,247,4.72535342928,-15.68629765188,13.61132828181,2,1,18
+2025-03-11T12:43:07.011154,479392989,731,247,5.29013670768,-16.966044878445,14.58027559728,2,1,18
+2025-03-11T12:43:07.136154,479392989,731,247,5.82197429484,-18.181105113375,15.525710341065,2,1,18
+2025-03-11T12:43:07.261154,479392989,731,247,6.33498577272,-19.340733529305,16.447711743855,2,1,18
+2025-03-11T12:43:07.386154,479392989,731,247,6.81975808668,-20.44953290835,17.304702710805,2,1,18
+2025-03-11T12:43:07.511154,479392989,731,247,7.28099776404,-21.498276425535,18.096644762145,2,1,18
+2025-03-11T12:43:07.636154,479392989,731,247,7.70929175016,-22.463865127305,18.8649769068,2,1,18
+2025-03-11T12:43:07.761154,479392989,731,247,8.10934657236,-23.383241748135,19.58218330041,2,1,18
+2025-03-11T12:43:07.886154,479392989,731,247,8.49057528528,-24.23333568213,20.23430229864,2,1,18
+2025-03-11T12:43:08.011154,479392989,731,247,8.824738725,-25.018721363745,20.84901781095,2,1,18
+2025-03-11T12:43:08.136154,479392989,731,247,9.14478258276,-25.73483144544,21.403276232625,2,1,18
+2025-03-11T12:43:08.261154,479392989,731,247,9.4365872766,-26.377027710525,21.906262900755,2,1,18
+2025-03-11T12:43:08.386154,479392989,731,247,9.69073975188,-26.9175942495,22.33933096932,2,1,18
+2025-03-11T12:43:08.511154,479392989,731,247,9.89782695396,-27.402686447985,22.716563751405,2,1,18
+2025-03-11T12:43:08.636154,479392989,731,247,10.08608804676,-27.82311291558,23.014873120815,2,1,18
+2025-03-11T12:43:08.761154,479392989,731,247,10.22257733904,-28.14188839632,23.27095402956,2,1,18
+2025-03-11T12:43:08.886154,479392989,731,247,10.31670788544,-28.377494887815,23.45720348601,2,1,18
+2025-03-11T12:43:09.011154,479392989,731,247,10.39671884988,-28.55305969128,23.592284753355,2,1,18
+2025-03-11T12:43:09.136154,479392989,731,247,10.43437106844,-28.61775376983,23.638908097845,2,1,18
+2025-03-11T12:43:09.261154,479392989,731,247,10.44378412308,-28.622384899605,23.648193041085,2,1,18
+2025-03-11T12:43:09.386154,479392989,731,247,10.41083843184,-28.543847040135,23.578406298,2,1,18
+2025-03-11T12:43:09.511154,479392989,731,247,10.31670788544,-28.37287793187,23.452559035245,2,1,18
+2025-03-11T12:43:09.636154,479392989,731,247,10.19904470244,-28.114151226075,23.266136971395,2,1,18
+2025-03-11T12:43:09.761154,479392989,731,247,10.06726193748,-27.79538283225,22.99158578232,2,1,18
+2025-03-11T12:43:09.886154,479392989,731,247,9.883707372,-27.388814319405,22.65639866577,2,1,18
+2025-03-11T12:43:10.011001,479392993,721,248,9.67662016992,-26.88525429714,22.279068548685,2,1,18
+2025-03-11T12:43:10.136001,479392993,721,248,9.42246769464,-26.33083689033,21.832067127825,2,1,18
+2025-03-11T12:43:10.261001,479392993,721,248,9.14948911008,-25.688668972905,21.329121210615,2,1,18
+2025-03-11T12:43:10.386001,479392993,721,248,8.85768441624,-24.958750544865,20.770230797055,2,1,18
+2025-03-11T12:43:10.511001,479392993,721,248,8.50940139456,-24.164109690615,20.1692964051,2,1,18
+2025-03-11T12:43:10.636001,479392993,721,248,8.13287920896,-23.3001719757,19.48939389126,2,1,18
+2025-03-11T12:43:10.761001,479392993,721,248,7.73753091408,-22.371568529895,18.79062948594,2,1,18
+2025-03-11T12:43:10.886001,479392993,721,248,7.295117346,-21.382873787655,18.01752499233,2,1,18
+2025-03-11T12:43:11.011001,479392993,721,248,6.81505155936,-20.329484966865,17.21627762229,2,1,18
+2025-03-11T12:43:11.136001,479392993,721,248,6.32086619076,-19.22067141399,16.345405928835,2,1,18
+2025-03-11T12:43:11.261001,479392993,721,248,5.81726776752,-18.06105717189,15.42804501852,2,1,18
+2025-03-11T12:43:11.386001,479392993,721,248,5.27601712572,-16.822897983405,14.482468230525,2,1,18
+2025-03-11T12:43:11.511001,479392993,721,248,4.72535342928,-15.552405929475,13.48125932664,2,1,18
+2025-03-11T12:43:11.636001,479392993,721,248,4.16057015088,-14.231106099405,12.461271720255,2,1,18
+2025-03-11T12:43:11.761001,479392993,721,248,3.54872159928,-12.85894888479,11.41319386323,2,1,18
+2025-03-11T12:43:11.886001,479392993,721,248,2.92745999304,-11.459075760675,10.346469160185,2,1,18
+2025-03-11T12:43:12.011001,479392993,721,248,2.29678533216,-10.01301890328,9.219419222985,2,1,18
+2025-03-11T12:43:12.136001,479392993,721,248,1.66611067128,-8.55311117805,8.06919569946,2,1,18
+2025-03-11T12:43:12.261001,479392993,721,248,1.02131642844,-7.065480456405,6.9049352592,2,1,18
+2025-03-11T12:43:12.386001,479392993,721,248,0.35769607632,-5.563970519265,5.74056106677,2,1,18
+2025-03-11T12:43:12.511001,479392993,721,248,-0.31533733044,-4.03012771668,4.54827546054,2,1,18
+2025-03-11T12:43:12.636001,479392993,721,248,-0.99778379184,-2.48241987243,3.342036126555,2,1,18
+2025-03-11T12:43:12.761001,479392993,721,248,-1.68964330788,-0.94393176624,2.13582508461,2,1,18
+2025-03-11T12:43:12.886001,479392993,721,248,-2.3767962966,0.61763403276,0.94336291269,2,1,18
+2025-03-11T12:43:13.011001,479392993,721,248,-3.059242758,2.197660568625,-0.263046757545,2,1,18
+2025-03-11T12:43:13.136001,479392993,721,248,-3.75110227404,3.77770127832,-1.464856686225,2,1,18
+2025-03-11T12:43:13.261001,479392993,721,248,-4.4241356808,5.33462886063,-2.66188407822,2,1,18
+2025-03-11T12:43:13.386001,479392993,721,248,-5.10187561488,6.86847875013,-3.86342010621,2,1,18
+2025-03-11T12:43:13.511001,479392993,721,248,-5.76078943968,8.388449424135,-5.04636191397,2,1,18
+2025-03-11T12:43:13.636001,479392993,721,248,-6.42911631912,9.90843427197,-6.215463746145,2,1,18
+2025-03-11T12:43:13.761001,479392993,721,248,-7.09273667124,11.396093341275,-7.370524703295,2,1,18
+2025-03-11T12:43:13.886001,479392993,721,248,-7.7187048048,12.823675287975,-8.488226883735,2,1,18
+2025-03-11T12:43:14.010956,479392997,718,249,-8.354085993,14.251271408505,-9.59208908859,2,1,18
+2025-03-11T12:43:14.135956,479392997,718,249,-8.97064107192,15.641903533815,-10.667995170435,2,1,18
+2025-03-11T12:43:14.260956,479392997,718,249,-9.55895698692,16.986323578185,-11.702015735265,2,1,18
+2025-03-11T12:43:14.385956,479392997,718,249,-10.1425663746,18.29380088808,-12.708110740275,2,1,18
+2025-03-11T12:43:14.510956,479392997,718,249,-10.68852354372,19.52273325159,-13.676749633575,2,1,18
+2025-03-11T12:43:14.635956,479392997,718,249,-11.2015350216,20.71006340319,-14.608137272895,2,1,18
+2025-03-11T12:43:14.760956,479392997,718,249,-11.72866608144,21.869713079865,-15.511688770815,2,1,18
+2025-03-11T12:43:14.885956,479392997,718,249,-12.20873186808,22.96465450416,-16.350116080725,2,1,18
+2025-03-11T12:43:15.010956,479392997,718,249,-12.65585196348,23.990291980875,-17.1650064852,2,1,18
+2025-03-11T12:43:15.135956,479392997,718,249,-13.0841459496,24.974348506425,-17.90109514575,2,1,18
+2025-03-11T12:43:15.260956,479392997,718,249,-13.4842007718,25.87064034753,-18.59969940255,2,1,18
+2025-03-11T12:43:15.385956,479392997,718,249,-13.8371903208,26.69760698031,-19.237775254605,2,1,18
+2025-03-11T12:43:15.510956,479392997,718,249,-14.18076681516,27.464539011975,-19.8293132223,2,1,18
+2025-03-11T12:43:15.635956,479392997,718,249,-14.49139761828,28.15293318417,-20.36030468094,2,1,18
+2025-03-11T12:43:15.760956,479392997,718,249,-14.75966967552,28.753541411175,-20.839920821595,2,1,18
+2025-03-11T12:43:15.885956,479392997,718,249,-14.99499604152,29.2848456906,-21.24517876965,2,1,18
+2025-03-11T12:43:16.010956,479392997,718,249,-15.19267018896,29.75607284742,-21.603837706965,2,1,18
+2025-03-11T12:43:16.135956,479392997,718,249,-15.36210517248,30.13491836385,-21.8695465026,2,1,18
+2025-03-11T12:43:16.260956,479392997,718,249,-15.49859446476,30.430609064865,-22.116265508565,2,1,18
+2025-03-11T12:43:16.385956,479392997,718,249,-15.59743153848,30.647754819495,-22.2885674667,2,1,18
+2025-03-11T12:43:16.510956,479392997,718,249,-15.65861639364,30.78635562774,-22.377212142975,2,1,18
+2025-03-11T12:43:16.635956,479392997,718,249,-15.67744250292,30.83255353485,-22.423697401545,2,1,18
+2025-03-11T12:43:16.760956,479392997,718,249,-15.649203339,30.818660145525,-22.40046268884,2,1,18
+2025-03-11T12:43:16.885956,479392997,718,249,-15.61625764776,30.712420550385,-22.330529943255,2,1,18
+2025-03-11T12:43:17.010956,479392997,718,249,-15.53624668332,30.50915401125,-22.18606243938,2,1,18
+2025-03-11T12:43:17.135956,479392997,718,249,-15.42329002764,30.23196656859,-21.967212409155,2,1,18
+2025-03-11T12:43:17.260956,479392997,718,249,-15.2726811534,29.88085113549,-21.68320989888,2,1,18
+2025-03-11T12:43:17.385956,479392997,718,249,-15.06559395132,29.451162408345,-21.343230057915,2,1,18
+2025-03-11T12:43:17.510956,479392997,718,249,-14.83968063996,28.924489258695,-20.93801681907,2,1,18
+2025-03-11T12:43:17.635956,479392997,718,249,-14.59494121932,28.323916466265,-20.49079243617,2,1,18
+2025-03-11T12:43:17.760956,479392997,718,249,-14.31725610744,27.68635841787,-19.96938019692,2,1,18
+2025-03-11T12:43:17.885956,479392997,718,249,-13.9783861404,26.951752164735,-19.387262987235,2,1,18
+2025-03-11T12:43:18.010925,479393001,716,250,-13.61598353676,26.14785613785,-18.772389013545,2,1,18
+2025-03-11T12:43:18.135925,479393001,716,250,-13.23475482384,25.27467742413,-18.092427644475,2,1,18
+2025-03-11T12:43:18.260925,479393001,716,250,-12.83470000164,24.313748199795,-17.36114189607,2,1,18
+2025-03-11T12:43:18.385925,479393001,716,250,-12.38757990624,23.28811072308,-16.5785923107,2,1,18
+2025-03-11T12:43:18.510925,479393001,716,250,-11.92634022888,22.21628242617,-15.75880788852,2,1,18
+2025-03-11T12:43:18.635925,479393001,716,250,-11.41803527832,21.10744761255,-14.887905631875,2,1,18
+2025-03-11T12:43:18.760925,479393001,716,250,-10.89090421848,19.929330112095,-13.965776330895,2,1,18
+2025-03-11T12:43:18.885925,479393001,716,250,-10.34965357668,18.705021791445,-13.00179207609,2,1,18
+2025-03-11T12:43:19.010925,479393001,716,250,-9.78487029828,17.402189785155,-12.000382272765,2,1,18
+2025-03-11T12:43:19.135925,479393001,716,250,-9.21067396524,16.071641869365,-10.966465272375,2,1,18
+2025-03-11T12:43:19.260925,479393001,716,250,-8.60353194096,14.69487478572,-9.913753152315,2,1,18
+2025-03-11T12:43:19.385925,479393001,716,250,-7.98227033472,13.29961861755,-8.823952197945,2,1,18
+2025-03-11T12:43:19.510925,479393001,716,250,-7.3421826192,11.85816454227,-7.696906219035,2,1,18
+2025-03-11T12:43:19.635925,479393001,716,250,-6.706801431,10.379781906345,-6.569675757855,2,1,18
+2025-03-11T12:43:19.760925,479393001,716,250,-6.0478876062,8.882896012065,-5.40071596989,2,1,18
+2025-03-11T12:43:19.885925,479393001,716,250,-5.38426725408,7.362918251145,-4.213143857385,2,1,18
+2025-03-11T12:43:20.010925,479393001,716,250,-4.72535342928,5.829096709305,-3.01626869733,2,1,18
+2025-03-11T12:43:20.135925,479393001,716,250,-4.02878738592,4.276750648365,-1.81459458342,2,1,18
+2025-03-11T12:43:20.260925,479393001,716,250,-3.34634092452,2.72442584817,-0.6129510327,2,1,18
+2025-03-11T12:43:20.385925,479393001,716,250,-2.64977488116,1.15361196345,0.59806065024,2,1,18
+2025-03-11T12:43:20.510925,479393001,716,250,-1.95791536512,-0.426428746245,1.79063034489,2,1,18
+2025-03-11T12:43:20.635925,479393001,716,250,-1.28488195836,-1.983356328555,3.006138204945,2,1,18
+2025-03-11T12:43:20.760925,479393001,716,250,-0.588315915,-3.535702389495,4.217052552885,2,1,18
+2025-03-11T12:43:20.885925,479393001,716,250,0.10825012836,-5.08343149449,5.400221864985,2,1,18
+2025-03-11T12:43:21.010925,479393001,716,250,0.75775089852,-6.612621906555,6.583191964785,2,1,18
+2025-03-11T12:43:21.135925,479393001,716,250,1.411958196,-8.114117669865,7.75216589877,2,1,18
+2025-03-11T12:43:21.260925,479393001,716,250,2.06616549348,-9.57406082967,8.911680594975,2,1,18
+2025-03-11T12:43:21.385925,479393001,716,250,2.70154668168,-11.03859259776,10.03421793789,2,1,18
+2025-03-11T12:43:21.510925,479393001,716,250,3.3181017606,-12.452309502795,11.110245688485,2,1,18
+2025-03-11T12:43:21.635925,479393001,716,250,3.9064176756,-13.805963459055,12.17665573992,2,1,18
+2025-03-11T12:43:21.760925,479393001,716,250,4.4947335906,-15.15500045937,13.206080521485,2,1,18
+2025-03-11T12:43:21.885925,479393001,716,250,5.07363645096,-16.45323677046,14.230597139325,2,1,18
+2025-03-11T12:43:22.010879,479393005,713,251,5.61488709276,-17.672928135165,15.18531682635,2,1,18
+2025-03-11T12:43:22.135879,479393005,713,251,6.13260509796,-18.86026537368,16.10747441937,2,1,18
+2025-03-11T12:43:22.260879,479393005,713,251,6.64091004852,-19.992184967025,16.98311846178,2,1,18
+2025-03-11T12:43:22.385879,479393005,713,251,7.11626930784,-21.077885392515,17.807626565415,2,1,18
+2025-03-11T12:43:22.510879,479393005,713,251,7.54926982128,-22.075799872815,18.589999585095,2,1,18
+2025-03-11T12:43:22.635879,479393005,713,251,7.96344422544,-23.03213340195,19.325911679955,2,1,18
+2025-03-11T12:43:22.760879,479393005,713,251,8.34937946568,-23.914553114475,20.00131178724,2,1,18
+2025-03-11T12:43:22.885879,479393005,713,251,8.71178206932,-24.70921522947,20.61613709343,2,1,18
+2025-03-11T12:43:23.010879,479393005,713,251,9.04123898172,-25.45765817661,21.18444657786,2,1,18
+2025-03-11T12:43:23.135879,479393005,713,251,9.33304367556,-26.118322265475,21.692150698005,2,1,18
+2025-03-11T12:43:23.260879,479393005,713,251,9.59660920548,-26.71430644962,22.15325184912,2,1,18
+2025-03-11T12:43:23.385879,479393005,713,251,9.82252251684,-27.23174568738,22.567656654495,2,1,18
+2025-03-11T12:43:23.510879,479393005,713,251,10.00607708232,-27.656782024005,22.90756122306,2,1,18
+2025-03-11T12:43:23.635879,479393005,713,251,10.1660990112,-28.026379454715,23.182441209765,2,1,18
+2025-03-11T12:43:23.760879,479393005,713,251,10.29317524884,-28.308205114065,23.38286566887,2,1,18
+2025-03-11T12:43:23.885879,479393005,713,251,10.37318621328,-28.497620785365,23.53188028851,2,1,18
+2025-03-11T12:43:24.010879,479393005,713,251,10.42966454112,-28.57619407941,23.61557832129,2,1,18
+2025-03-11T12:43:24.135879,479393005,713,251,10.42966454112,-28.608512771025,23.648089476645,2,1,18
+2025-03-11T12:43:24.260879,479393005,713,251,10.41554495916,-28.557704994885,23.610830306085,2,1,18
+2025-03-11T12:43:24.385879,479393005,713,251,10.37318621328,-28.414515578355,23.49448134489,2,1,18
+2025-03-11T12:43:24.510879,479393005,713,251,10.26493608492,-28.197355649895,23.32677912831,2,1,18
+2025-03-11T12:43:24.635879,479393005,713,251,10.1425663746,-27.910920121515,23.10323993811,2,1,18
+2025-03-11T12:43:24.760879,479393005,713,251,9.98254444572,-27.53670573486,22.800614915565,2,1,18
+2025-03-11T12:43:24.885879,479393005,713,251,9.7895768256,-27.093187400625,22.43287193445,2,1,18
+2025-03-11T12:43:25.010879,479393005,713,251,9.56366351424,-26.557280339085,22.027610028105,2,1,18
+2025-03-11T12:43:25.135879,479393005,713,251,9.27656534772,-25.91970811686,21.561618817575,2,1,18
+2025-03-11T12:43:25.260879,479393005,713,251,8.96122801728,-25.235923813695,21.02602138794,2,1,18
+2025-03-11T12:43:25.385879,479393005,713,251,8.63177110488,-24.469013042775,20.434513983435,2,1,18
+2025-03-11T12:43:25.510879,479393005,713,251,8.2599554466,-23.6281671945,19.77784391115,2,1,18
+2025-03-11T12:43:25.635879,479393005,713,251,7.883433261,-22.736527743915,19.083935043765,2,1,18
+2025-03-11T12:43:25.760879,479393005,713,251,7.45043274756,-21.78016586712,18.329501729925,2,1,18
+2025-03-11T12:43:25.885879,479393005,713,251,7.01743223412,-20.75454965115,17.5331223567,2,1,18
+2025-03-11T12:43:26.010818,479393009,709,252,6.53736644748,-19.65499127091,16.690050596025,2,1,18
+2025-03-11T12:43:26.135818,479393009,709,252,6.0243549696,-18.509213722815,15.814323364635,2,1,18
+2025-03-11T12:43:26.260818,479393009,709,252,5.50193043708,-17.294167661715,14.88738946437,2,1,18
+2025-03-11T12:43:26.385818,479393009,709,252,4.95126674064,-16.042143431565,13.913998597575,2,1,18
+2025-03-11T12:43:26.510818,479393009,709,252,4.39118998956,-14.74855242408,12.90340741545,2,1,18
+2025-03-11T12:43:26.635818,479393009,709,252,3.80758060188,-13.404139466625,11.855536687305,2,1,18
+2025-03-11T12:43:26.760818,479393009,709,252,3.20514510492,-12.045847293675,10.775211387885,2,1,18
+2025-03-11T12:43:26.885818,479393009,709,252,2.57917697136,-10.62288230292,9.685254243285,2,1,18
+2025-03-11T12:43:27.010818,479393009,709,252,1.93908925584,-9.167577359805,8.56275538014,2,1,18
+2025-03-11T12:43:27.135818,479393009,709,252,1.28488195836,-7.703017244055,7.403216350185,2,1,18
+2025-03-11T12:43:27.260818,479393009,709,252,0.61655507892,-6.187649352165,6.23413885176,2,1,18
+2025-03-11T12:43:27.385818,479393009,709,252,-0.05647832784,-4.66304046147,5.06038238109,2,1,18
+2025-03-11T12:43:27.510818,479393009,709,252,-0.72009867996,-3.138445744605,3.863545700805,2,1,18
+2025-03-11T12:43:27.635818,479393009,709,252,-1.3884255594,-1.57229133732,2.661859712025,2,1,18
+2025-03-11T12:43:27.760818,479393009,709,252,-2.08499160276,-0.0014774526,1.46470838013,2,1,18
+2025-03-11T12:43:27.885818,479393009,709,252,-2.7768511188,1.55547847737,0.239919535125,2,1,18
+2025-03-11T12:43:28.010818,479393009,709,252,-3.4592975802,3.1216541454,-0.96641713386,2,1,18
+2025-03-11T12:43:28.135818,479393009,709,252,-4.1417440416,4.692446769375,-2.19587872167,2,1,18
+2025-03-11T12:43:28.260818,479393009,709,252,-4.82889703032,6.23092778865,-3.38821922484,2,1,18
+2025-03-11T12:43:28.385818,479393009,709,252,-5.50193043708,7.76938754718,-4.58052916482,2,1,18
+2025-03-11T12:43:28.510818,479393009,709,252,-6.15143120724,9.289344047355,-5.749590246075,2,1,18
+2025-03-11T12:43:28.635818,479393009,709,252,-6.80563850472,10.76775503094,-6.90920227728,2,1,18
+2025-03-11T12:43:28.760818,479393009,709,252,-7.46925885684,12.246180188355,-8.041113981855,2,1,18
+2025-03-11T12:43:28.885818,479393009,709,252,-8.10934657236,13.68301730769,-9.149655158955,2,1,18
+2025-03-11T12:43:29.010818,479393009,709,252,-8.7306081786,15.073656519915,-10.239431779575,2,1,18
+2025-03-11T12:43:29.135818,479393009,709,252,-9.32363062092,16.450402342815,-11.29673345346,2,1,18
+2025-03-11T12:43:29.260818,479393009,709,252,-9.89782695396,17.75786547888,-12.325908668085,2,1,18
+2025-03-11T12:43:29.385818,479393009,709,252,-10.4484906504,19.014506664975,-13.294703751615,2,1,18
+2025-03-11T12:43:29.510818,479393009,709,252,-10.98032823756,20.257268635575,-14.244904614915,2,1,18
+2025-03-11T12:43:29.635818,479393009,709,252,-11.51216582472,21.426159311055,-15.14389485105,2,1,18
+2025-03-11T12:43:29.760818,479393009,709,252,-11.98752508404,22.521093648435,-16.005412558305,2,1,18
+2025-03-11T12:43:29.885818,479393009,709,252,-12.4487647614,23.57907107751,-16.834364213265,2,1,18
+2025-03-11T12:43:30.010757,479393013,705,253,-12.88647180216,24.576992644725,-17.607507186645,2,1,18
+2025-03-11T12:43:30.135757,479393013,705,253,-13.295939679,25.49176648344,-18.31084927092,2,1,18
+2025-03-11T12:43:30.260757,479393013,705,253,-13.69128797388,26.364966457905,-18.976980852135,2,1,18
+2025-03-11T12:43:30.385757,479393013,705,253,-14.04427752288,27.154997443125,-19.582521215085,2,1,18
+2025-03-11T12:43:30.510757,479393013,705,253,-14.354908326,27.87109335099,-20.16447996339,2,1,18
+2025-03-11T12:43:30.635757,479393013,705,253,-14.62788691056,28.504027356525,-20.6673772131,2,1,18
+2025-03-11T12:43:30.760757,479393013,705,253,-14.8961589678,29.08616775975,-21.082214380545,2,1,18
+2025-03-11T12:43:30.885757,479393013,705,253,-15.11265922452,29.57589108801,-21.464111988855,2,1,18
+2025-03-11T12:43:31.010757,479393013,705,253,-15.28680073536,29.97782847108,-21.78539404515,2,1,18
+2025-03-11T12:43:31.135757,479393013,705,253,-15.42799655496,30.315078862515,-22.041582476625,2,1,18
+2025-03-11T12:43:31.260757,479393013,705,253,-15.54095321064,30.583032393285,-22.228043020245,2,1,18
+2025-03-11T12:43:31.385757,479393013,705,253,-15.61155112044,30.74011519914,-22.358386460115,2,1,18
+2025-03-11T12:43:31.510757,479393013,705,253,-15.63979028436,30.827879883585,-22.414351331925,2,1,18
+2025-03-11T12:43:31.635757,479393013,705,253,-15.65861639364,30.837142143135,-22.41906086736,2,1,18
+2025-03-11T12:43:31.760757,479393013,705,253,-15.63508375704,30.749384545605,-22.367726300295,2,1,18
+2025-03-11T12:43:31.885757,479393013,705,253,-15.56448584724,30.615386519475,-22.246744763205,2,1,18
+2025-03-11T12:43:32.010757,479393013,705,253,-15.4609422462,30.365914986315,-22.051161696015,2,1,18
+2025-03-11T12:43:32.135757,479393013,705,253,-15.32445295392,30.056373417465,-21.799749571785,2,1,18
+2025-03-11T12:43:32.260757,479393013,705,253,-15.14560491576,29.65442894748,-21.48769756179,2,1,18
+2025-03-11T12:43:32.385757,479393013,705,253,-14.943224241,29.164726879965,-21.119690867715,2,1,18
+2025-03-11T12:43:32.510757,479393013,705,253,-14.70319134768,28.59186291012,-20.69572326012,2,1,18
+2025-03-11T12:43:32.635757,479393013,705,253,-14.4019735992,27.97273725093,-20.215938470355,2,1,18
+2025-03-11T12:43:32.760757,479393013,705,253,-14.10075585072,27.275123340675,-19.67105836863,2,1,18
+2025-03-11T12:43:32.885757,479393013,705,253,-13.76188588368,26.489730572145,-19.070193019635,2,1,18
+2025-03-11T12:43:33.010757,479393013,705,253,-13.3900702254,25.63965081198,-18.408854162835,2,1,18
+2025-03-11T12:43:33.135757,479393013,705,253,-12.97589582124,24.711019018515,-17.71466912361,2,1,18
+2025-03-11T12:43:33.260757,479393013,705,253,-12.54760183512,23.717728581075,-16.946190976455,2,1,18
+2025-03-11T12:43:33.385757,479393013,705,253,-12.0957752124,22.673616193665,-16.126572932235,2,1,18
+2025-03-11T12:43:33.510757,479393013,705,253,-11.61100289844,21.578667682455,-15.26503484952,2,1,18
+2025-03-11T12:43:33.635757,479393013,705,253,-11.1074044752,20.419053440355,-14.37077452428,2,1,18
+2025-03-11T12:43:33.760757,479393013,705,253,-10.58968647,19.20401446617,-13.406889875625,2,1,18
+2025-03-11T12:43:33.885757,479393013,705,253,-10.0249031916,17.915033327715,-12.42403354161,2,1,18
+2025-03-11T12:43:34.010681,479393017,700,254,-9.44129380392,16.612172973765,-11.40872263632,2,1,18
+2025-03-11T12:43:34.135681,479393017,700,254,-8.8482713616,15.263128886535,-10.351566964935,2,1,18
+2025-03-11T12:43:34.260681,479393017,700,254,-8.24112933732,13.84942615533,-9.2755595898,2,1,18
+2025-03-11T12:43:34.385681,479393017,700,254,-7.60574814912,12.41259612291,-8.162408483415,2,1,18
+2025-03-11T12:43:34.510681,479393017,700,254,-6.95624737896,10.95266005002,-7.026004560015,2,1,18
+2025-03-11T12:43:34.635681,479393017,700,254,-6.32086619076,9.46042654626,-5.870980395495,2,1,18
+2025-03-11T12:43:34.760681,479393017,700,254,-5.65253931132,7.949675610315,-4.706547347835,2,1,18
+2025-03-11T12:43:34.885681,479393017,700,254,-4.9889189592,6.429697849395,-3.514355118315,2,1,18
+2025-03-11T12:43:35.010681,479393017,700,254,-4.3064724978,4.8773730492,-2.312711567595,2,1,18
+2025-03-11T12:43:35.135681,479393017,700,254,-3.61931950908,3.32504116209,-1.10643771213,2,1,18
+2025-03-11T12:43:35.260681,479393017,700,254,-2.93216652036,1.749624495255,0.090717578055,2,1,18
+2025-03-11T12:43:35.385681,479393017,700,254,-2.24972005896,0.19729969506,1.310841596835,2,1,18
+2025-03-11T12:43:35.510681,479393017,700,254,-1.56256707024,-1.37350001583,2.52645302133,2,1,18
+2025-03-11T12:43:35.635681,479393017,700,254,-0.89894671812,-2.935030380255,3.73734472266,2,1,18
+2025-03-11T12:43:35.760681,479393017,700,254,-0.20708720208,-4.4689015305,4.92043084578,2,1,18
+2025-03-11T12:43:35.885681,479393017,700,254,0.47535925932,-5.993524595025,6.098827808925,2,1,18
+2025-03-11T12:43:36.010681,479393017,700,254,1.13897961144,-7.49965148811,7.253986101075,2,1,18
+2025-03-11T12:43:36.135681,479393017,700,254,1.78377385428,-8.987282209755,8.399766073275,2,1,18
+2025-03-11T12:43:36.260681,479393017,700,254,2.4238615698,-10.456438020705,9.554678756775,2,1,18
+2025-03-11T12:43:36.385681,479393017,700,254,3.05453623068,-11.88402705432,10.663150890915,2,1,18
+2025-03-11T12:43:36.510681,479393017,700,254,3.66167825496,-13.26541109391,11.725127578755,2,1,18
+2025-03-11T12:43:36.635681,479393017,700,254,4.27823333388,-14.605256703825,12.759184936215,2,1,18
+2025-03-11T12:43:36.760681,479393017,700,254,4.84301661228,-15.926556533895,13.7791725426,2,1,18
+2025-03-11T12:43:36.885681,479393017,700,254,5.39368030872,-17.197048587825,14.752660744395,2,1,18
+2025-03-11T12:43:37.010681,479393017,700,254,5.92551789588,-18.384407087085,15.693329368665,2,1,18
+2025-03-11T12:43:37.135681,479393017,700,254,6.4244097918,-19.539397286325,16.58293505541,2,1,18
+2025-03-11T12:43:37.260681,479393017,700,254,6.89976905112,-20.63894857965,17.444477096415,2,1,18
+2025-03-11T12:43:37.385681,479393017,700,254,7.37983483776,-21.66463566477,18.24095834694,2,1,18
+2025-03-11T12:43:37.510681,479393017,700,254,7.79871576924,-22.634827148655,18.990813981825,2,1,18
+2025-03-11T12:43:37.635681,479393017,700,254,8.20347711876,-23.54497694451,19.71260201268,2,1,18
+2025-03-11T12:43:37.760681,479393017,700,254,8.5658797224,-24.376574707065,20.350722573945,2,1,18
+2025-03-11T12:43:37.885681,479393017,700,254,8.90945621676,-25.138889782785,20.956096558935,2,1,18
+2025-03-11T12:43:38.010635,479393021,697,255,9.21538049256,-25.85959555968,21.50110851714,2,1,18
+2025-03-11T12:43:38.135635,479393021,697,255,9.4836525498,-26.4925224783,21.98551511106,2,1,18
+2025-03-11T12:43:38.260635,479393021,697,255,9.72368544312,-27.02383384464,22.41388383192,2,1,18
+2025-03-11T12:43:38.385635,479393021,697,255,9.94489222716,-27.476628612255,22.76787625587,2,1,18
+2025-03-11T12:43:38.510635,479393021,697,255,10.10962068336,-27.87393486555,23.070633134895,2,1,18
+2025-03-11T12:43:38.635635,479393021,697,255,10.23199039368,-28.17883821771,23.30813001114,2,1,18
+2025-03-11T12:43:38.760635,479393021,697,255,10.33553399472,-28.40984192709,23.47589504124,2,1,18
+2025-03-11T12:43:38.885635,479393021,697,255,10.42025148648,-28.553095125855,23.592335692005,2,1,18
+2025-03-11T12:43:39.010635,479393021,697,255,10.42966454112,-28.62236363886,23.648162477895,2,1,18
+2025-03-11T12:43:39.135635,479393021,697,255,10.43437106844,-28.61775376983,23.6250477468,2,1,18
+2025-03-11T12:43:39.260635,479393021,697,255,10.38730579524,-28.502259002055,23.555035770525,2,1,18
+2025-03-11T12:43:39.385635,479393021,697,255,10.32141441276,-28.308247635555,23.406027380325,2,1,18
+2025-03-11T12:43:39.510635,479393021,697,255,10.2131642844,-28.044918147645,23.191880656095,2,1,18
+2025-03-11T12:43:39.635635,479393021,697,255,10.05314235552,-27.69840549666,22.930982689185,2,1,18
+2025-03-11T12:43:39.760635,479393021,697,255,9.85546820808,-27.287198767125,22.60036079271,2,1,18
+2025-03-11T12:43:39.885635,479393021,697,255,9.63896795136,-26.77439065914,22.213721398635,2,1,18
+2025-03-11T12:43:40.010635,479393021,697,255,9.39893505804,-26.201526689295,21.77127332298,2,1,18
+2025-03-11T12:43:40.135635,479393021,697,255,9.11183689152,-25.540869687345,21.26819950758,2,1,18
+2025-03-11T12:43:40.260635,479393021,697,255,8.8012060884,-24.810922911645,20.695407992055,2,1,18
+2025-03-11T12:43:40.385635,479393021,697,255,8.45762959404,-24.01628914431,20.06676308574,2,1,18
+2025-03-11T12:43:40.510635,479393021,697,255,8.06698782648,-23.15233016865,19.391450125725,2,1,18
+2025-03-11T12:43:40.635635,479393021,697,255,7.648106895,-22.20522346449,18.66019662765,2,1,18
+2025-03-11T12:43:40.760635,479393021,697,255,7.2245194362,-21.202706202075,17.87781964968,2,1,18
+2025-03-11T12:43:40.885635,479393021,697,255,6.76327975884,-20.140111817055,17.044223543955,2,1,18
+2025-03-11T12:43:41.010635,479393021,697,255,6.2596813356,-18.998965398735,16.187021489835,2,1,18
+2025-03-11T12:43:41.135635,479393021,697,255,5.74666985772,-17.80701829119,15.264849750795,2,1,18
+2025-03-11T12:43:41.260635,479393021,697,255,5.21012574324,-16.591950969345,14.31940481928,2,1,18
+2025-03-11T12:43:41.385635,479393021,697,255,4.62651635556,-15.326026262955,13.318148935035,2,1,18
+2025-03-11T12:43:41.510635,479393021,697,255,4.0476134952,-14.00470517214,12.293510648445,2,1,18
+2025-03-11T12:43:41.635635,479393021,697,255,3.44517799824,-12.60947735163,11.231471147085,2,1,18
+2025-03-11T12:43:41.760635,479393021,697,255,2.81450333736,-11.191122229905,10.13690803149,2,1,18
+2025-03-11T12:43:41.885635,479393021,697,255,2.1885352038,-9.763540283205,9.02844608508,2,1,18
+2025-03-11T12:43:42.010574,479393025,693,256,1.54374096096,-8.29437738534,7.868903096835,2,1,18
+2025-03-11T12:43:42.135574,479393025,693,256,0.88953366348,-6.81134944581,6.71850696591,2,1,18
+2025-03-11T12:43:42.260574,479393025,693,256,0.23061983868,-5.291378771805,5.521704807105,2,1,18
+2025-03-11T12:43:42.385574,479393025,693,256,-0.43300051344,-3.74831623116,4.338631142865,2,1,18
+2025-03-11T12:43:42.510574,479393025,693,256,-1.11544697484,-2.20060838691,3.15087227694,2,1,18
+2025-03-11T12:43:42.635574,479393025,693,256,-1.8120130182,-0.6205605903,1.935191809485,2,1,18
+2025-03-11T12:43:42.760574,479393025,693,256,-2.51328558888,0.950260381335,0.724169938815,2,1,18
+2025-03-11T12:43:42.885574,479393025,693,256,-3.19573205028,2.497968225585,-0.50054986323,2,1,18
+2025-03-11T12:43:43.010574,479393025,693,256,-3.87347198436,4.08260463048,-1.70235356247,2,1,18
+2025-03-11T12:43:43.135574,479393025,693,256,-4.54650539112,5.625681344955,-2.8946878362,2,1,18
+2025-03-11T12:43:43.260574,479393025,693,256,-5.2477779618,7.16880058092,-4.08708323631,2,1,18
+2025-03-11T12:43:43.385574,479393025,693,256,-5.92081136856,8.69802642756,-5.265484157745,2,1,18
+2025-03-11T12:43:43.510574,479393025,693,256,-6.57972519336,10.20414623373,-6.429872496195,2,1,18
+2025-03-11T12:43:43.635574,479393025,693,256,-7.23393249084,11.673323305425,-7.584815742885,2,1,18
+2025-03-11T12:43:43.760574,479393025,693,256,-7.86931367904,13.12400420568,-8.70728008455,2,1,18
+2025-03-11T12:43:43.885574,479393025,693,256,-8.49057528528,14.54696210952,-9.783366690375,2,1,18
+2025-03-11T12:43:44.010574,479393025,693,256,-9.09771730956,15.914495281275,-10.854510610995,2,1,18
+2025-03-11T12:43:44.135574,479393025,693,256,-9.6954462792,17.24507863164,-11.906959018095,2,1,18
+2025-03-11T12:43:44.260574,479393025,693,256,-10.24610997564,18.54327242124,-12.912934041495,2,1,18
+2025-03-11T12:43:44.385574,479393025,693,256,-10.78265409012,19.7906584347,-13.853929192245,2,1,18
+2025-03-11T12:43:44.510574,479393025,693,256,-11.31449167728,20.973399978015,-14.78071313172,2,1,18
+2025-03-11T12:43:44.635574,479393025,693,256,-11.82279662784,22.100702615415,-15.670193191425,2,1,18
+2025-03-11T12:43:44.760574,479393025,693,256,-12.28874283252,23.17253799924,-16.489987801335,2,1,18
+2025-03-11T12:43:44.885574,479393025,693,256,-12.72174334596,24.184303347375,-17.29553440734,2,1,18
+2025-03-11T12:43:45.010574,479393025,693,256,-13.14062427744,25.149877875315,-18.0222651234,2,1,18
+2025-03-11T12:43:45.135574,479393025,693,256,-13.52655951768,26.04153149973,-18.69309378117,2,1,18
+2025-03-11T12:43:45.260574,479393025,693,256,-13.91249475792,26.868547740915,-19.331240947335,2,1,18
+2025-03-11T12:43:45.385574,479393025,693,256,-14.23253861568,27.607742602335,-19.91334173985,2,1,18
+2025-03-11T12:43:45.510574,479393025,693,256,-14.52434330952,28.273023647145,-20.448790895835,2,1,18
+2025-03-11T12:43:45.635574,479393025,693,256,-14.79261536676,28.86439796226,-20.896017549885,2,1,18
+2025-03-11T12:43:45.760574,479393025,693,256,-15.03264826008,29.3957093286,-21.3105259197,2,1,18
+2025-03-11T12:43:45.885574,479393025,693,256,-15.21149629824,29.84844031398,-21.65518642005,2,1,18
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_ena_sim_metakernel.template b/imap_processing/tests/spice/test_data/imap_ena_sim_metakernel.template
deleted file mode 100644
index 6d4f45dbb9..0000000000
--- a/imap_processing/tests/spice/test_data/imap_ena_sim_metakernel.template
+++ /dev/null
@@ -1,8 +0,0 @@
-{SPICE_TEST_DATA_PATH}/imap_sclk_0000.tsc
-{SPICE_TEST_DATA_PATH}/naif0012.tls
-{SPICE_TEST_DATA_PATH}/imap_spk_demo.bsp
-{SPICE_TEST_DATA_PATH}/sim_1yr_imap_attitude.bc
-{SPICE_TEST_DATA_PATH}/imap_wkcp.tf
-{SPICE_TEST_DATA_PATH}/de440s.bsp
-{SPICE_TEST_DATA_PATH}/imap_science_100.tf
-{SPICE_TEST_DATA_PATH}/sim_1yr_imap_pointing_frame.bc
\ No newline at end of file
diff --git a/imap_processing/tests/spice/test_data/imap_ialirt_sim_metakernel.template b/imap_processing/tests/spice/test_data/imap_ialirt_sim_metakernel.template
deleted file mode 100644
index 740567a037..0000000000
--- a/imap_processing/tests/spice/test_data/imap_ialirt_sim_metakernel.template
+++ /dev/null
@@ -1 +0,0 @@
-{SPICE_TEST_DATA_PATH}/imap_wkcp.tf
\ 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_simple_metakernel.template b/imap_processing/tests/spice/test_data/imap_simple_metakernel.template
deleted file mode 100644
index d727ba3183..0000000000
--- a/imap_processing/tests/spice/test_data/imap_simple_metakernel.template
+++ /dev/null
@@ -1,3 +0,0 @@
-{SPICE_TEST_DATA_PATH}/imap_sclk_0000.tsc
-{SPICE_TEST_DATA_PATH}/naif0012.tls
-{SPICE_TEST_DATA_PATH}/imap_spk_demo.bsp
\ No newline at end of file
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 4f065600bc..8e0465ba03 100644
--- a/imap_processing/tests/spice/test_geometry.py
+++ b/imap_processing/tests/spice/test_geometry.py
@@ -14,14 +14,22 @@
cartesian_to_spherical,
frame_transform,
frame_transform_az_el,
+ get_instrument_mounting_az_el,
get_rotation_matrix,
get_spacecraft_to_instrument_spin_phase_offset,
imap_state,
instrument_pointing,
+ lo_instrument_pointing,
solar_longitude,
spherical_to_cartesian,
)
-from imap_processing.spice.kernels import ensure_spice
+
+
+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(
@@ -31,7 +39,7 @@
np.linspace(798033670, 798033770),
],
)
-def test_imap_state(et, use_test_metakernel):
+def test_imap_state(et, imap_simple_sim_metakernel):
"""Test coverage for imap_state()"""
state = imap_state(et, observer=SpiceBody.EARTH)
if hasattr(et, "__len__"):
@@ -41,34 +49,77 @@ def test_imap_state(et, use_test_metakernel):
@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_imap_state_ecliptic():
+def test_imap_state_ecliptic(imap_ena_sim_metakernel):
"""Tests retrieving IMAP state in the ECLIPJ2000 frame"""
state = imap_state(798033670)
assert state.shape == (6,)
@pytest.mark.parametrize(
- "instrument, expected_offset",
+ "instrument, expected_az_el",
[
- (SpiceFrame.IMAP_LO_BASE, 330 / 360),
- (SpiceFrame.IMAP_HI_45, 255 / 360),
- (SpiceFrame.IMAP_HI_90, 285 / 360),
- (SpiceFrame.IMAP_ULTRA_45, 33 / 360),
- (SpiceFrame.IMAP_ULTRA_90, 210 / 360),
- (SpiceFrame.IMAP_SWAPI, 168 / 360),
- (SpiceFrame.IMAP_IDEX, 90 / 360),
- (SpiceFrame.IMAP_CODICE, 136 / 360),
- (SpiceFrame.IMAP_HIT, 30 / 360),
- (SpiceFrame.IMAP_SWE, 153 / 360),
- (SpiceFrame.IMAP_GLOWS, 127 / 360),
- (SpiceFrame.IMAP_MAG, 0 / 360),
+ # Expected spin-phase offsets based on 7516-0011_drw.pdf
+ (SpiceFrame.IMAP_LO_BASE, (60, 0)), # (330 + 90) % 360 = 60
+ # 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
+ (SpiceFrame.IMAP_IDEX, (180, -45)), # 90 + 90 = 180
+ (SpiceFrame.IMAP_CODICE, (226, 0)), # 136 + 90 = 226
+ (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_I, (90, 0)), # 0 + 90 = 90
+ (SpiceFrame.IMAP_MAG_O, (90, 0)), # 0 + 90 = 90
],
)
-def test_get_spacecraft_to_instrument_spin_phase_offset(instrument, expected_offset):
+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_130.tf"]):
+ result = get_instrument_mounting_az_el(instrument)
+ # 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,
+ SpiceFrame.IMAP_HI_45,
+ SpiceFrame.IMAP_HI_90,
+ SpiceFrame.IMAP_ULTRA_45,
+ SpiceFrame.IMAP_ULTRA_90,
+ SpiceFrame.IMAP_SWAPI,
+ SpiceFrame.IMAP_IDEX,
+ SpiceFrame.IMAP_CODICE,
+ SpiceFrame.IMAP_HIT,
+ SpiceFrame.IMAP_SWE,
+ SpiceFrame.IMAP_GLOWS,
+ SpiceFrame.IMAP_MAG_I,
+ SpiceFrame.IMAP_MAG_O,
+ ],
+)
+def test_get_spacecraft_to_instrument_spin_phase_offset(
+ furnish_kernels, spice_test_data_path, instrument
+):
"""Test coverage for get_spacecraft_to_instrument_spin_phase_offset()"""
- result = get_spacecraft_to_instrument_spin_phase_offset(instrument)
- assert result == expected_offset
+ # Test that the offset is close to SPICE derived mounting azimuth
+ 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)
@pytest.mark.parametrize(
@@ -117,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",
]
@@ -145,7 +196,9 @@ def test_frame_transform(et_strings, position, from_frame, to_frame, furnish_ker
if position.ndim == 1:
position = np.broadcast_to(position, (len(et), 3))
result = np.broadcast_to(result, (len(et), 3))
- for spice_et, spice_position, test_result in zip(et, position, result):
+ for spice_et, spice_position, test_result in zip(
+ et, position, result, strict=False
+ ):
rotation_matrix = spiceypy.pxform(from_frame.name, to_frame.name, spice_et)
spice_result = spiceypy.mxv(rotation_matrix, spice_position)
np.testing.assert_allclose(test_result, spice_result, atol=1e-12)
@@ -239,13 +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_science_100.tf",
+ "imap_130.tf",
+ "imap_sclk_0000.tsc",
+ "imap_science_120.tf",
"sim_1yr_imap_attitude.bc",
"sim_1yr_imap_pointing_frame.bc",
"de440s.bsp",
@@ -257,22 +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_science_100.tf",
+ "imap_130.tf",
+ "imap_sclk_0000.tsc",
+ "imap_science_120.tf",
"sim_1yr_imap_attitude.bc",
"sim_1yr_imap_pointing_frame.bc",
]
@@ -296,13 +459,100 @@ 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
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_basis_vectors():
+def test_basis_vectors(imap_ena_sim_metakernel):
"""Test coverage for basis_vectors()."""
- # This call to SPICE needs to be wrapped with `ensure_spice` so that kernels
- # get furnished automatically
- et = ensure_spice(spiceypy.utc2et)("2025-09-30T12:00:00.000")
+ et = spiceypy.utc2et("2025-09-30T12:00:00.000")
# test input of float
sc_axes = basis_vectors(et, SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.IMAP_SPACECRAFT)
np.testing.assert_array_equal(sc_axes, np.eye(3))
@@ -311,7 +561,7 @@ def test_basis_vectors():
sc_axes = basis_vectors(et_array, SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.ECLIPJ2000)
assert sc_axes.shape == (10, 3, 3)
# Verify that for each time, the basis vectors are correct
- for et, basis_matrix in zip(et_array, sc_axes):
+ for et, basis_matrix in zip(et_array, sc_axes, strict=False):
np.testing.assert_array_equal(
basis_matrix,
frame_transform(
diff --git a/imap_processing/tests/spice/test_kernels.py b/imap_processing/tests/spice/test_kernels.py
deleted file mode 100644
index e2ddbd3d02..0000000000
--- a/imap_processing/tests/spice/test_kernels.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""Tests coverage for imap_processing/spice/kernels.py"""
-
-import pytest
-import spiceypy
-from spiceypy.utils.exceptions import SpiceyError
-
-from imap_processing.spice.kernels import ensure_spice
-
-
-@ensure_spice
-def single_wrap_et2utc(et, fmt, prec):
- """Directly decorate a spice function with ensure_spice for use in tests"""
- return spiceypy.et2utc(et, fmt, prec)
-
-
-@ensure_spice
-def double_wrap_et2utc(et, fmt, prec):
- """Decorate a spice function twice with ensure_spice for use in tests. This
- simulates some decorated outer functions that call lower level functions
- that are already decorated."""
- return single_wrap_et2utc(et, fmt, prec)
-
-
-@ensure_spice(time_kernels_only=True)
-def single_wrap_et2utc_tk_only(et, fmt, prec):
- """Directly wrap a spice function with optional time_kernels_only set True"""
- return spiceypy.et2utc(et, fmt, prec)
-
-
-@ensure_spice(time_kernels_only=True)
-def double_wrap_et2utc_tk_only(et, fmt, prec):
- """Decorate a spice function twice with ensure_spice for use in tests. This
- simulates some decorated outer functions that call lower level functions
- that are already decorated."""
- return single_wrap_et2utc(et, fmt, prec)
-
-
-@pytest.mark.parametrize(
- "func",
- [
- single_wrap_et2utc,
- single_wrap_et2utc_tk_only,
- double_wrap_et2utc,
- double_wrap_et2utc_tk_only,
- ],
-)
-def test_ensure_spice_emus_mk_path(func, use_test_metakernel):
- """Test functionality of ensure spice with SPICE_METAKERNEL set"""
- assert func(577365941.184, "ISOC", 3) == "2018-04-18T23:24:31.998"
-
-
-@pytest.mark.xfail(reason="Fix this test once we add metakernel in the imap_cli")
-@pytest.mark.usefixtures("_unset_metakernel_path")
-def test_ensure_spice_time_kernels():
- """Test functionality of ensure spice with timekernels set"""
- wrapped = ensure_spice(spiceypy.et2utc, time_kernels_only=True)
- # TODO: Update/remove this test when a decision has been made about
- # whether IMAP will use the time_kernels_only functionality and the
- # ensure_spice decorator has been update.
- with pytest.raises(NotImplementedError):
- _ = wrapped(577365941.184, "ISOC", 3) == "2018-04-18T23:24:31.998"
-
-
-@pytest.mark.xfail(reason="Fix this test once we add metakernel in the imap_cli")
-@pytest.mark.usefixtures("_unset_metakernel_path")
-def test_ensure_spice_key_error():
- """Test functionality of ensure spice when all branches fail"""
- wrapped = ensure_spice(spiceypy.et2utc)
- # The ensure_spice decorator should raise a SpiceyError when all attempts to
- # furnish a set of kernels with sufficient coverage for the spiceypy
- # functions that it decorates.
- with pytest.raises(SpiceyError):
- _ = wrapped(577365941.184, "ISOC", 3) == "2018-04-18T23:24:31.998"
diff --git a/imap_processing/tests/spice/test_pointing_frame.py b/imap_processing/tests/spice/test_pointing_frame.py
index 78f351a12b..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,37 +10,54 @@
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
-def pointing_frame_kernels(spice_test_data_path):
+def furnish_pointing_frame_kernels(furnish_kernels, spice_test_data_path):
"""List SPICE kernels."""
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",
]
- kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
- return kernels
+ with furnish_kernels(required_kernels):
+ yield [str(spice_test_data_path / k) for k in required_kernels]
@pytest.fixture
-def et_times(pointing_frame_kernels):
- """Tests get_et_times function."""
- spiceypy.furnsh(pointing_frame_kernels)
+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."""
ck_kernel, _, _, _ = spiceypy.kdata(0, "ck")
ck_cover = spiceypy.ckcov(ck_kernel, -43000, True, "INTERVAL", 0, "TDB")
et_start, et_end = spiceypy.wnfetd(ck_cover, 0)
@@ -49,33 +67,53 @@ def et_times(pointing_frame_kernels):
# 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.
et_times = np.linspace(
- np.ceil(et_start * 1e6) / 1e6, np.floor(et_end * 1e6) / 1e6, int(num_samples)
+ np.ceil(et_start * 1e6) / 1e6,
+ np.floor(et_end * 1e6) / 1e6,
+ int(num_samples),
)
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",
[
@@ -88,13 +126,12 @@ def test_write_pointing_frame_ck(
segment_end_offset,
quaternion,
segment_id,
- pointing_frame_kernels,
+ furnish_pointing_frame_kernels,
tmp_path,
):
"""Test coverage for write_pointing_frame_ck"""
- spiceypy.furnsh(pointing_frame_kernels)
ck_cover = spiceypy.ckcov(
- pointing_frame_kernels[-1],
+ furnish_pointing_frame_kernels[-1],
SpiceFrame.IMAP_SPACECRAFT,
True,
"INTERVAL",
@@ -120,6 +157,8 @@ def test_write_pointing_frame_ck(
write_pointing_frame_ck(pointing_ck, segment_data, parent_file)
assert pointing_ck.exists()
+ # Using spiceypy.furnsh here is OK because it is inside of the furnish_kernels
+ # context manager which will clear this kernel upon exit
spiceypy.furnsh(str(pointing_ck.resolve()))
# Verify the correct # of segments
p_cover = spiceypy.ckcov(
@@ -145,25 +184,33 @@ def test_write_pointing_frame_ck(
assert parent_file in lines[5]
-def test_average_quaternions(et_times, pointing_frame_kernels):
- """Tests average_quaternions function."""
- spiceypy.furnsh(pointing_frame_kernels)
- 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, pointing_frame_kernels):
+def test_create_rotation_matrix(et_times, furnish_pointing_frame_kernels):
"""Tests create_rotation_matrix function."""
- spiceypy.furnsh(pointing_frame_kernels)
- 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(
- [[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
+ [
+ [0.0000, 0.0000, 1.0000],
+ [0.9104, -0.4136, 0.0000],
+ [0.4136, 0.9104, 0.0000],
+ ]
)
z_avg_expected = np.array([0.4136, 0.9104, 0.0000])
@@ -183,15 +230,12 @@ def get_ck_met_coverage(ck_path: str):
def test_calculate_pointing_attitude_segments(
spice_test_data_path,
- pointing_frame_kernels,
+ furnish_pointing_frame_kernels,
tmp_path,
et_times,
use_fake_repoint_data_for_time,
):
"""Tests create_pointing_frame function."""
- spiceypy.kclear()
- spiceypy.furnsh(pointing_frame_kernels)
-
# Set up the fake repoint data to coincide with the test CK
# Define 2 repoints:
@@ -200,63 +244,76 @@ def test_calculate_pointing_attitude_segments(
# 2. Starts one second before the CK ends, ends 10 seconds after the CK ends
# Result is the pointing starts 1-second after the CK start and ends 1-second
# before the CK end
- ck_met_start, ck_met_end = get_ck_met_coverage(pointing_frame_kernels[-1])
+ ck_met_start, ck_met_end = get_ck_met_coverage(furnish_pointing_frame_kernels[-1])
use_fake_repoint_data_for_time(
np.array([ck_met_start - 10, ck_met_end - 1]),
np.array([ck_met_start + 1, ck_met_end + 10]),
)
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
rotation_matrix_expected = np.array(
- [[0.0000, 0.0000, 1.0000], [0.9104, -0.4136, 0.0000], [0.4136, 0.9104, 0.0000]]
+ [
+ [0.0000, 0.0000, 1.0000],
+ [0.9104, -0.4136, 0.0000],
+ [0.4136, 0.9104, 0.0000],
+ ]
)
np.testing.assert_almost_equal(
- spiceypy.q2m(segment_data["quaternion"][0]), rotation_matrix_expected, decimal=4
+ spiceypy.q2m(segment_data["quaternion"][0]),
+ rotation_matrix_expected,
+ decimal=4,
)
- # Tests error handling when incorrect kernel is loaded.
- spiceypy.furnsh(pointing_frame_kernels)
- 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(
- pointing_frame_kernels, spice_test_data_path, use_fake_repoint_data_for_time
+ furnish_pointing_frame_kernels,
+ spice_test_data_path,
+ use_fake_repoint_data_for_time,
):
"""Tests create_pointing_frame function with multiple pointing kernels."""
- spiceypy.furnsh(pointing_frame_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(pointing_frame_kernels[-1])
+ 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 bcc463d98d..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
@@ -70,6 +71,86 @@ def test_interpolate_repoint_data(fake_repoint_data):
np.testing.assert_array_equal(repoint_df[key].values, expected_array)
+def test_get_pointing_times(fake_repoint_data):
+ """Test coverage for get_pointing_times function."""
+ times = 6
+ expected_times = (5.1, 15.2)
+
+ pointing_start_time, pointing_end_time = repoint.get_pointing_times(times)
+
+ assert pointing_start_time == expected_times[0]
+ 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 9714780c82..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,
],
],
@@ -97,11 +100,24 @@ def test_interpolate_spin_data(query_met_times, expected, fake_spin_data):
)
+@pytest.mark.parametrize(
+ "met_time,spin_number_expected", [(0, 0), (14.9, 0), (15.1, 1), (32, 2)]
+)
+def test_get_spin_number(fake_spin_data, met_time, spin_number_expected):
+ """Test get_spin_number() with generated spin data."""
+ # Call the function
+ spin_number = spin.get_spin_number(met_time=met_time)
+
+ # Test the value
+ assert spin_number == spin_number_expected
+
+
@pytest.mark.parametrize(
"query_met_times, 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),
@@ -111,18 +127,24 @@ def test_interpolate_spin_data(query_met_times, expected, fake_spin_data):
(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):
@@ -172,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"):
@@ -202,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."
@@ -253,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,
@@ -264,16 +287,28 @@ 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(instrument, fake_spin_data):
+def test_get_instrument_spin_phase(
+ instrument, fake_spin_data, furnish_kernels, spice_test_data_path
+):
"""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])
- inst_phase = spin.get_instrument_spin_phase(met_times, instrument)
+ 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 b31c8be518..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,
@@ -33,7 +34,7 @@ def test_met_to_sclkticks(met):
np.testing.assert_array_equal(ticks, expected)
-def test_met_to_ttj2000ns(furnish_time_kernels):
+def test_met_to_ttj2000ns():
"""Test coverage for met_to_ttj2000ns function."""
utc = "2026-01-01T00:00:00.125"
et = spiceypy.str2et(utc)
@@ -51,7 +52,7 @@ def test_met_to_ttj2000ns(furnish_time_kernels):
np.testing.assert_array_equal(tt, np.array(spicey_tt * 1e9))
-def test_ttj2000ns_to_et(furnish_time_kernels):
+def test_ttj2000ns_to_et():
"""Test coverage for ttj2000ns_to_et function."""
# Use spice to come up with reasonable J2000 values
utc = "2025-09-23T00:00:00.000"
@@ -72,7 +73,7 @@ def test_ttj2000ns_to_et(furnish_time_kernels):
np.testing.assert_array_equal(j2000s, ets)
-def test_et_to_ttj2000ns(furnish_time_kernels):
+def test_et_to_ttj2000ns():
"""Test coverage for ttj2000ns_to_et function."""
# Use spice to come up with reasonable J2000 values
utc = "2025-09-23T00:00:00.000"
@@ -112,7 +113,7 @@ def test_et_to_ttj2000ns(furnish_time_kernels):
),
],
)
-def test_met_to_utc(furnish_time_kernels, expected_utc, precision):
+def test_met_to_utc(expected_utc, precision):
"""Test coverage for met_to_utc function."""
if isinstance(expected_utc, list):
et_arr = spiceypy.str2et(expected_utc)
@@ -136,7 +137,7 @@ def test_met_to_utc(furnish_time_kernels, expected_utc, precision):
],
],
)
-def test_met_to_datetime64(furnish_time_kernels, utc):
+def test_met_to_datetime64(utc):
"""Test coverage for met_to_datetime64 function."""
if isinstance(utc, list):
expected_dt64 = np.array([np.datetime64(utc_str) for utc_str in utc])
@@ -160,7 +161,9 @@ def test_met_to_datetime64(furnish_time_kernels, utc):
@pytest.mark.parametrize("sclk_ticks", [0.0, np.arange(10)])
-def test_sct_to_et(sclk_ticks):
+def test_sct_to_et(
+ sclk_ticks,
+):
"""Test for `sct_to_et` function."""
et = sct_to_et(sclk_ticks)
if isinstance(sclk_ticks, float):
@@ -170,7 +173,9 @@ def test_sct_to_et(sclk_ticks):
@pytest.mark.parametrize("sclk_ticks", [0.0, np.arange(10)])
-def test_sct_to_ttj2000s(sclk_ticks):
+def test_sct_to_ttj2000s(
+ sclk_ticks,
+):
"""Test for `sct_to_ttj2000s` function."""
tt = sct_to_ttj2000s(sclk_ticks)
if isinstance(sclk_ticks, float):
@@ -179,7 +184,7 @@ def test_sct_to_ttj2000s(sclk_ticks):
assert len(tt) == len(sclk_ticks)
-def test_str_to_et(furnish_time_kernels):
+def test_str_to_et():
"""Test coverage for string to et conversion function."""
utc = "2017-07-14T19:46:00"
# Test single value input
@@ -214,7 +219,7 @@ def test_str_to_et(furnish_time_kernels):
assert np.array_equal(expected_et_array, actual_et_array)
-def test_et_to_utc(furnish_time_kernels):
+def test_et_to_utc():
"""Test coverage for et to utc conversion function."""
et = 553333629.1837274
# Test single value input
@@ -235,7 +240,7 @@ def test_et_to_utc(furnish_time_kernels):
assert np.array_equal(expected_utc_array, actual_utc_array)
-def test_et_to_datetime(furnish_time_kernels):
+def test_et_to_datetime():
et = 553333629.1837274
# Test single value input
expected_dt = np.datetime64("2017-07-14T19:46:00.000")
@@ -257,7 +262,7 @@ def test_epoch_to_doy():
assert np.all(doy == expected_doy)
-def test_et_to_met(furnish_time_kernels):
+def test_et_to_met():
"""Test coverage for et_to_met function."""
utc = "2026-01-01T00:00:00.125"
et = spiceypy.str2et(utc)
@@ -278,7 +283,7 @@ def test_et_to_met(furnish_time_kernels):
np.testing.assert_array_almost_equal(met_array, expected_met_array)
-def test_ttj2000ns_to_met(furnish_time_kernels):
+def test_ttj2000ns_to_met():
"""Test coverage for ttj2000ns_to_met function."""
# Test roundtrip: MET -> TTJ2000ns -> MET
original_met = 1000.0
@@ -293,3 +298,108 @@ def test_ttj2000ns_to_met(furnish_time_kernels):
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 38587654db..49ddd2fa50 100644
--- a/imap_processing/tests/swapi/test_swapi_l1.py
+++ b/imap_processing/tests/swapi/test_swapi_l1.py
@@ -84,7 +84,7 @@ def test_decompress_count():
# compressed + no-overflow, compressed + overflow, no compression
raw_values = np.array([[12, 0xFFFF, 12]])
compression_flag = np.array([[1, 1, 0]])
- expected = np.array([[12 * 16, np.iinfo(np.int32).max, 12]], dtype=np.int32)
+ expected = np.array([[12 * 16, np.iinfo(np.int32).max, 12]], dtype=np.float32)
returned_value = decompress_count(raw_values, compression_flag)
np.testing.assert_array_equal(returned_value, expected)
@@ -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 acb6a4ff8d..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
@@ -10,12 +11,14 @@
from imap_processing.cdf.utils import load_cdf, write_cdf
from imap_processing.swapi.l1.swapi_l1 import swapi_l1
from imap_processing.swapi.l2.swapi_l2 import (
- TIME_PER_BIN,
+ SWAPI_LIVETIME,
solve_full_sweep_energy,
swapi_l2,
)
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"] / TIME_PER_BIN,
+ 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 d0c2206076..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,9 +268,18 @@ 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",
+ return_value=153 / 360,
+)
@pytest.mark.usefixtures("use_fake_spin_data_for_time")
def test_swe_l2_15sec(
+ mock_phase_offset,
mock_get_file_paths,
use_fake_spin_data_for_time,
l2_sector_validation_df,
@@ -308,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,
@@ -359,9 +395,18 @@ 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",
+ return_value=153 / 360,
+)
@pytest.mark.usefixtures("use_fake_spin_data_for_time")
def test_swe_l2_14_6sec(
+ mock_phase_offset,
mock_get_file_paths,
use_fake_spin_data_for_time,
l2_binned_flux_14sec_validation_df,
diff --git a/imap_processing/tests/test_cli.py b/imap_processing/tests/test_cli.py
index bdc1cc59bb..bef5bc06bf 100644
--- a/imap_processing/tests/test_cli.py
+++ b/imap_processing/tests/test_cli.py
@@ -6,7 +6,9 @@
import sys
from pathlib import Path
from unittest import mock
+from unittest.mock import Mock, sentinel
+import imap_data_access.io
import numpy as np
import pytest
import spiceypy
@@ -16,6 +18,7 @@
ProcessingInputCollection,
ScienceInput,
SPICEInput,
+ SpinInput,
)
from imap_processing.cli import (
@@ -24,7 +27,7 @@
Hi,
Hit,
Idex,
- ProcessInstrument,
+ Lo,
Spacecraft,
Swe,
Ultra,
@@ -35,6 +38,13 @@
from imap_processing.spice import config as spice_config
+@pytest.fixture(autouse=True)
+def clear_spice_kernels():
+ """Fixture to clear SPICE kernels before each test."""
+ with spiceypy.KernelPool([]):
+ yield
+
+
@pytest.fixture
def mock_instrument_dependencies():
with (
@@ -179,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"})
@@ -190,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
@@ -201,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
@@ -272,30 +284,60 @@ def test_post_processing_returns_empty_list_if_invoked_with_no_data(
@pytest.mark.parametrize(
- "data_level, science_input, anc_input, n_prods",
+ "data_level, data_descriptor, function_name, science_input, anc_input, n_prods",
[
- ("l1a", ["imap_hi_l0_raw_20231212_v001.pkts"], [], 2),
- ("l1b", ["imap_hi_l1a_90sensor-de_20241105_v001.cdf"], [], 1),
- ("l1b", ["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",
+ "imap_hi_l1b_90sensor-hk_20241105_v001.cdf",
+ ],
+ ["imap_hi_90sensor-esa-energies_20240101_v001.csv"],
+ 1,
+ ),
+ ("l1b", "sci", "housekeeping", ["imap_hi_l0_raw_20231212_v001.pkts"], [], 2),
(
"l1c",
- ["imap_hi_l1b_45sensor-de_20250415_v001.cdf"],
- ["imap_hi_calibration-prod-config_20240101_v001.csv"],
+ "45sensor-pset",
+ "hi_l1c",
+ [
+ "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,
),
],
)
def test_hi(
- mock_instrument_dependencies, data_level, science_input, anc_input, n_prods
+ mock_instrument_dependencies,
+ data_level,
+ data_descriptor,
+ function_name,
+ science_input,
+ anc_input,
+ n_prods,
):
"""Test coverage for cli.Hi class"""
mocks = mock_instrument_dependencies
@@ -310,14 +352,20 @@ def test_hi(
# patch autospec=True makes this test confirm that the function call in cli.py
# matches the mocked function signature.
with mock.patch(
- f"imap_processing.cli.hi_{data_level}.hi_{data_level}", autospec=True
+ f"imap_processing.cli.hi_{data_level}.{function_name}", autospec=True
) as mock_hi:
mock_hi.return_value = [xr.Dataset()] * n_prods
dependency_str = (
'[{"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()
@@ -325,6 +373,141 @@ 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)
+@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"
+
+ mock_loaded_pset_1 = Mock(attrs={"Logical_source": "some_pset_logical_source"})
+ pset_file_paths = [
+ "imap_lo_l1c_pset_20250415_v001.cdf",
+ "imap_lo_l1c_pset_20250416_v001.cdf",
+ ]
+
+ processing_input = ProcessingInputCollection(
+ *[ScienceInput(file_path) for file_path in pset_file_paths],
+ )
+
+ mocks["mock_load_cdf"].side_effect = [mock_loaded_pset_1, sentinel.loaded_pset_2]
+ mock_lo_pre_processing.return_value = processing_input
+
+ output_l2_dataset = xr.Dataset()
+ mock_lo_l2.return_value = [output_l2_dataset]
+
+ instrument = Lo(
+ "l2",
+ descriptor,
+ processing_input.serialize(),
+ "20250415",
+ "20250715",
+ "v005",
+ False,
+ )
+ instrument.process()
+
+ mock_lo_l2.assert_called_once_with(
+ {"some_pset_logical_source": [mock_loaded_pset_1, sentinel.loaded_pset_2]},
+ [],
+ descriptor,
+ )
+ 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"""
@@ -378,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()
@@ -474,12 +657,40 @@ 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"""
mocks = mock_instrument_dependencies
- mock_idex_l2b.return_value = xr.Dataset()
- mocks["mock_write_cdf"].side_effect = ["/path/to/product0"]
+ mock_idex_l2b.return_value = [xr.Dataset(), xr.Dataset()]
+ mocks["mock_write_cdf"].side_effect = ["/path/to/product0", "/path/to/product1"]
input_collection = ProcessingInputCollection(
ScienceInput("imap_idex_l1b_evt_20251015_v002.cdf"),
ScienceInput("imap_idex_l2a_sci-1week_20251017_v018.cdf"),
@@ -489,14 +700,15 @@ def test_idex_l2b(mock_idex_l2b, mock_instrument_dependencies):
dependency_str = input_collection.serialize()
instrument = Idex(
- "l2b", "sci-1mo", dependency_str, "20100105", "20100101", "v001", False
+ "l2b", "all", dependency_str, "20100105", "20100101", "v001", False
)
instrument.process()
assert mock_idex_l2b.call_count == 1
- assert mock_instrument_dependencies["mock_write_cdf"].call_count == 1
+ 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"""
@@ -520,8 +732,7 @@ def test_hit_l1a(mock_hit_l1a, mock_instrument_dependencies):
assert mock_instrument_dependencies["mock_write_cdf"].call_count == 2
-@pytest.mark.usefixtures("_unset_metakernel_path")
-def test_spice_kernel_handling(spice_test_data_path):
+def test_spice_kernel_handling(spice_test_data_path, clear_spice_kernels):
"""Test coverage for ProcessInstrument.pre_processing method()."""
kernels_to_furnish = ["naif0012.tls", "imap_sclk_0000.tsc"]
dependency_obj = [
@@ -616,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
@@ -644,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"),
@@ -658,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/dps_exposure_helio_45_E1.cdf b/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E1.cdf
deleted file mode 100644
index 641be2396f..0000000000
Binary files a/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E1.cdf and /dev/null differ
diff --git a/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E12.cdf b/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E12.cdf
deleted file mode 100644
index dbd37741bb..0000000000
Binary files a/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E12.cdf and /dev/null differ
diff --git a/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E24.cdf b/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E24.cdf
deleted file mode 100644
index 451e685faa..0000000000
Binary files a/imap_processing/tests/ultra/data/l1/dps_exposure_helio_45_E24.cdf and /dev/null differ
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_l1b-45sensor-imgparams-lookup_20250101_v001.csv b/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-45sensor-imgparams-lookup_20250101_v001.csv
new file mode 100644
index 0000000000..99959529bf
--- /dev/null
+++ b/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-45sensor-imgparams-lookup_20250101_v001.csv
@@ -0,0 +1,2 @@
+ο»ΏXFTSC,XFTLTOFF,XFTRTOFF,TOFSC,TOFTPOFF,TOFBTOFF,XFTTOF,XCOINTPSC,XCOINTPOFF,XCOINBTSC,XCOINBTOFF,ETOFSC,ETOFTPOFF,ETOFBTOFF,TOFDiffTpMin,TOFDiffTpMax,TOFDiffBtMin,TOFDiffBtMax,eTOFMin,eTOFMax,eTOFSlope1,eTOFOff1,eTOFSlope2,eTOFOff2,SPTPPHOFF,SPBTPHOFF,YBKSSD0,YBKSSD1,YBKSSD2,YBKSSD3,YBKSSD4,YBKSSD5,YBKSSD6,YBKSSD7,TOFSSDSC,TOFSSDLTOFF0,TOFSSDLTOFF1,TOFSSDLTOFF2,TOFSSDLTOFF3,TOFSSDLTOFF4,TOFSSDLTOFF5,TOFSSDLTOFF6,TOFSSDLTOFF7,TOFSSDRTOFF0,TOFSSDRTOFF1,TOFSSDRTOFF2,TOFSSDRTOFF3,TOFSSDRTOFF4,TOFSSDRTOFF5,TOFSSDRTOFF6,TOFSSDRTOFF7,TOFSSDTOTOFF,PathSteepThresh,PathMediumThresh
+0.172998047,49.3,48.25,0.5,-528,-525,0.01831055,0.067929688,41.75,0.067929688,-40.75,0.1,-44.5,-44.5,226,266,222,262,-400,90,6827,100,7680,-50,580,580,29.3,37.3,7.1,15.1,-15.1,-7.1,-37.3,-29.3,0.196484375,-6,-7.3,-3.8,-4.2,-3.8,-3.7,-6.3,-5,-5,-6.3,-3.7,-3.8,-4,-4.2,-7.3,-6,5.9,5000,6500
\ No newline at end of file
diff --git a/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-90sensor-imgparams-lookup_20250101_v001.csv b/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-90sensor-imgparams-lookup_20250101_v001.csv
new file mode 100644
index 0000000000..9cfedc09e8
--- /dev/null
+++ b/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-90sensor-imgparams-lookup_20250101_v001.csv
@@ -0,0 +1,2 @@
+ο»ΏXFTSC,XFTLTOFF,XFTRTOFF,TOFSC,TOFTPOFF,TOFBTOFF,XFTTOF,XCOINTPSC,XCOINTPOFF,XCOINBTSC,XCOINBTOFF,ETOFSC,ETOFTPOFF,ETOFBTOFF,TOFDiffTpMin,TOFDiffTpMax,TOFDiffBtMin,TOFDiffBtMax,eTOFMin,eTOFMax,eTOFSlope1,eTOFOff1,eTOFSlope2,eTOFOff2,SPTPPHOFF,SPBTPHOFF,YBKSSD0,YBKSSD1,YBKSSD2,YBKSSD3,YBKSSD4,YBKSSD5,YBKSSD6,YBKSSD7,TOFSSDSC,TOFSSDLTOFF0,TOFSSDLTOFF1,TOFSSDLTOFF2,TOFSSDLTOFF3,TOFSSDLTOFF4,TOFSSDLTOFF5,TOFSSDLTOFF6,TOFSSDLTOFF7,TOFSSDRTOFF0,TOFSSDRTOFF1,TOFSSDRTOFF2,TOFSSDRTOFF3,TOFSSDRTOFF4,TOFSSDRTOFF5,TOFSSDRTOFF6,TOFSSDRTOFF7,TOFSSDTOTOFF,PathSteepThresh,PathMediumThresh
+0.176,48.8,48.25,0.5,-528,-525,0.01831055,0.068,40,0.068,-40,0.1,-43,-43,226,266,222,262,-400,100,6827,100,7680,-50,540,540,29.3,37.3,7.1,15.1,-15.1,-7.1,-37.3,-29.3,0.196484375,-6,-7.3,-3.8,-4.2,-3.8,-3.7,-6.3,-5,-5,-6.3,-3.7,-3.8,-4,-4.2,-7.3,-6,6.1,5000,6500
\ No newline at end of file
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 1e8e870ad7..ff8cd6b424 100644
--- a/imap_processing/tests/ultra/mock_data.py
+++ b/imap_processing/tests/ultra/mock_data.py
@@ -6,7 +6,7 @@
import xarray as xr
from imap_processing.ena_maps.utils.coordinates import CoordNames
-from imap_processing.spice.kernels import ensure_spice
+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
@@ -132,9 +132,7 @@ def get_binomial_counts(distance_scaling, lat_bin, central_lat_bin):
# Determine the epoch, which is TT time in nanoseconds since J2000 epoch
tdb_et = str_to_et(timestr)
- tt_j2000ns = (
- ensure_spice(spice.unitim, time_kernels_only=True)(tdb_et, "ET", "TT") * 1e9
- )
+ tt_j2000ns = spice.unitim(tdb_et, "ET", "TT") * 1e9
logical_source = f"imap_ultra_l1c_{head}sensor-spacecraftpset"
logical_file_id = (
@@ -169,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: [
@@ -195,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),
@@ -266,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)
@@ -288,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(
@@ -319,13 +325,15 @@ 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)
- tt_j2000ns = (
- ensure_spice(spice.unitim, time_kernels_only=True)(tdb_et, "ET", "TT") * 1e9
- )
+ tt_j2000ns = spice.unitim(tdb_et, "ET", "TT") * 1e9
logical_source = f"imap_ultra_l1c_{head}sensor-spacecraftpset"
logical_file_id = (
@@ -338,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,
),
@@ -348,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
@@ -356,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,
@@ -374,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 321fa1456a..bfd8a54990 100644
--- a/imap_processing/tests/ultra/unit/conftest.py
+++ b/imap_processing/tests/ultra/unit/conftest.py
@@ -1,10 +1,14 @@
"""Pytest plugin module for test data paths."""
+from unittest import mock
+
+import astropy_healpix.healpy as hp
import numpy as np
import pytest
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,
@@ -24,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,
@@ -35,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
@@ -262,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
@@ -450,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."""
@@ -480,7 +482,6 @@ def faux_aux_dataset():
return test_aux_dataset
-@pytest.mark.external_test_data
@pytest.fixture
def ancillary_files():
"""Fixture to return ancillary files."""
@@ -488,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
@@ -497,7 +500,9 @@ def ancillary_files():
"l1b-45sensor-rightslit-lookup": path
/ "imap_ultra_l1b-45sensor-rightslit-lookup_20250101_v000.csv",
"l1b-45sensor-imgparams-lookup": path
- / "imap_ultra_l1b-45sensor-imgparams-lookup_20250101_v000.csv",
+ / "imap_ultra_l1b-45sensor-imgparams-lookup_20250101_v001.csv",
+ "l1b-90sensor-imgparams-lookup": path
+ / "imap_ultra_l1b-90sensor-imgparams-lookup_20250101_v001.csv",
"l1b-45sensor-tdc-norm-lookup": path
/ "imap_ultra_l1b-45sensor-tdc-norm-lookup_20250101_v000.csv",
"l1b-45sensor-back-pos-lookup": path
@@ -512,36 +517,187 @@ def ancillary_files():
/ "imap_ultra_l1b-90sensor-sptpphcorr_20250101_v000.csv",
"l1b-90sensor-spbtphcorr": path
/ "imap_ultra_l1b-90sensor-spbtphcorr_20250101_v000.csv",
+ "l1b-45sensor-tofxeflat": path
+ / "imap_ultra_l1b-45sensor-tofxeflat_20250101_v000.pgm",
+ "l1b-45sensor-tofxemedium": path
+ / "imap_ultra_l1b-45sensor-tofxemedium_20250101_v000.pgm",
+ "l1b-45sensor-tofxesteep": path
+ / "imap_ultra_l1b-45sensor-tofxesteep_20250101_v000.pgm",
+ "l1b-90sensor-tofxeflat": path
+ / "imap_ultra_l1b-90sensor-tofxeflat_20250101_v000.pgm",
+ "l1b-90sensor-tofxemediu": path
+ / "imap_ultra_l1b-90sensor-tofxemedium_20250101_v000.pgm",
+ "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-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": 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)),
- }
+def mock_spacecraft_pointing_lookups():
+ """Test lookup tables fixture."""
+ 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"),
)
- # 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(
+ 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=(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_lookup.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(
{
- "imageratescadence": (["epoch"], modes),
- },
- coords={"epoch": ("epoch", np.arange(0, epoch, epoch / len(modes)))},
+ "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),
+ ),
+ }
)
- return {"rates": test_l1a_rates_dataset, "params": test_l1a_params_dataset}
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_865.py b/imap_processing/tests/ultra/unit/test_decom_apid_865.py
index a6d9e7c822..b0f03ef600 100644
--- a/imap_processing/tests/ultra/unit/test_decom_apid_865.py
+++ b/imap_processing/tests/ultra/unit/test_decom_apid_865.py
@@ -30,7 +30,7 @@ def test_process_cmd_echo(decom_test_data, cmd_echo_test_path):
np.testing.assert_array_equal(df.Opcode, decom_ultra["opcode"].values.flatten())
for i, (row, opcode) in enumerate(
- zip(decom_ultra["arguments"].values, decom_ultra["opcode"].values)
+ zip(decom_ultra["arguments"].values, decom_ultra["opcode"].values, strict=False)
):
expected_arg = df.Arguments.values[i].strip()
expected_len = len(expected_arg.split())
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
new file mode 100644
index 0000000000..d2149d4ea2
--- /dev/null
+++ b/imap_processing/tests/ultra/unit/test_l1c_lookup_utils.py
@@ -0,0 +1,204 @@
+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,
+)
+
+
+@pytest.mark.external_test_data
+def test_get_spacecraft_pointing_lookup_tables(ancillary_files):
+ """Test get_spacecraft_pointing_lookup_tables."""
+ instrument_id = 90
+ (
+ for_indices_by_spin_phase,
+ theta_vals,
+ phi_vals,
+ ra_and_dec,
+ boundary_scale_factors,
+ ) = get_spacecraft_pointing_lookup_tables(ancillary_files, instrument_id)
+ npix = hp.nside2npix(32) - 1 # test files dont have headers
+ # 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 == (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
+ assert theta_vals.dtype == np.float64
+ assert phi_vals.dtype == np.float64
+ assert ra_and_dec.dtype == np.float64
+ assert boundary_scale_factors.dtype == np.float64
+
+
+@pytest.mark.external_test_data
+def test_get_mask_below_fwhm_scattering_threshold(ancillary_files):
+ """Tests function get_mask_below_fwhm_scattering_threshold."""
+ energy = np.array([5]) # At energy 5, the FWHM threshold is 10
+ thresholds = get_scattering_thresholds_for_energy(energy, ancillary_files)
+ theta_coeffs = np.array(
+ [
+ [np.nan, 10], # This will result in a NaN value (False)
+ [5, -0.1], # FWHM value below the threshold (True)
+ [4, -0.1], # FWHM value below the threshold (True)
+ ]
+ )
+ phi_coeffs = np.array(
+ [
+ [3, -0.1], # FWHM value below the threshold (True)
+ [5, -0.1], # FWHM value below the threshold (True)
+ [15, -0.1], # FWHM value above the threshold (False)
+ ]
+ )
+ # 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, 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))
+ np.testing.assert_array_equal(pixel_mask, expected_pixel_mask)
+
+
+@pytest.mark.external_test_data
+def test_get_mask_below_fwhm_scattering_threshold_zero(ancillary_files):
+ """Tests function get_mask_below_fwhm_scattering_threshold."""
+ energy = np.array([0]) # At energy 0, the FWHM threshold is 0
+ thresholds = get_scattering_thresholds_for_energy(energy, ancillary_files)
+ theta_coeffs = np.array(
+ [
+ [np.nan, 10], # This will result in a NaN value (False)
+ [5, -0.1], # FWHM value below the threshold (True)
+ [4, -0.1], # FWHM value below the threshold (True)
+ ]
+ )
+ phi_coeffs = np.array(
+ [
+ [3, -0.1], # FWHM value below the threshold (True)
+ [5, -0.1], # FWHM value below the threshold (True)
+ [15, -0.1], # FWHM value above the threshold (False)
+ ]
+ )
+ # Since energy is zero, all should be False although some pixels are below threshold
+ expected_pixel_mask = np.array([[False], [False], [False]])
+ 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 6f036255a4..fe82d26668 100644
--- a/imap_processing/tests/ultra/unit/test_lookup_utils.py
+++ b/imap_processing/tests/ultra/unit/test_lookup_utils.py
@@ -5,16 +5,20 @@
import pytest
from imap_processing import imap_module_directory
-from imap_processing.quality_flags import ImapDEUltraFlags
+from imap_processing.quality_flags import ImapDEOutliersUltraFlags
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,
get_geometric_factor,
get_image_params,
get_norm,
get_ph_corrected,
+ get_scattering_coefficients,
+ get_scattering_thresholds,
get_y_adjust,
)
@@ -110,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):
@@ -121,9 +129,15 @@ def test_get_geometric_function(ancillary_files):
phi = np.array([-65, -64, -39, -1.3, 0, 1.3, 39, 64, 65])
theta = np.array([-65, -64, -39, -1.3, 0, 1.3, 39, 64, 65])
- quality_flags = np.full(phi.shape, ImapDEUltraFlags.NONE.value, dtype=np.uint16)
+ quality_flags = np.full(
+ phi.shape, ImapDEOutliersUltraFlags.NONE.value, dtype=np.uint16
+ )
gf = get_geometric_factor(
- ancillary_files, "l1b-sensor-gf-noblades", phi, theta, quality_flags
+ phi,
+ theta,
+ quality_flags,
+ ancillary_files,
+ "l1b-sensor-gf-noblades",
)
np.testing.assert_array_equal(
@@ -140,7 +154,9 @@ def test_get_ph_corrected(ancillary_files):
xlut = np.array([0, 10, 31, 32])
# Should be between 1 and 20 (0 and 19)
ylut = np.array([3, 10, 19, 32])
- quality_flags = np.full(xlut.shape, ImapDEUltraFlags.NONE.value, dtype=np.uint16)
+ quality_flags = np.full(
+ xlut.shape, ImapDEOutliersUltraFlags.NONE.value, dtype=np.uint16
+ )
ph_correct_top, quality_flags = get_ph_corrected(
"ultra45", "tp", ancillary_files, xlut, ylut, quality_flags
)
@@ -152,3 +168,128 @@ def test_get_ph_corrected(ancillary_files):
quality_flags,
np.array([0, 0, 2, 2]),
)
+
+
+@pytest.mark.external_test_data
+def test_get_ebins(ancillary_files):
+ """Tests function get_ph_corrected."""
+
+ energy = np.array([618, 4])
+ ctof = np.array([73, 24])
+ fillval_uint8 = 255
+ ebins = np.full(energy.shape, fillval_uint8, dtype=np.uint8)
+ ebins = get_ebins("l1b-tofxph", energy, ctof, ebins, ancillary_files)
+
+ np.testing.assert_array_equal(ebins, np.array([15, 19]))
+
+
+@pytest.mark.external_test_data
+def test_get_scattering_coefficients(ancillary_files):
+ """Tests function get_scattering_data."""
+
+ theta_coeffs, phi_coeffs = get_scattering_coefficients(
+ np.array([47, 43]),
+ np.array([43, 42]),
+ lookup_tables=None,
+ ancillary_files=ancillary_files,
+ instrument_id=45,
+ )
+ # Test a theta coefficients
+ np.testing.assert_array_equal(theta_coeffs[:, 0], np.array([np.nan, 35.23100]))
+ # Test b theta coefficients
+ np.testing.assert_array_equal(theta_coeffs[:, 1], np.array([np.nan, -0.72148]))
+ # Test a phi coefficients
+ np.testing.assert_array_equal(phi_coeffs[:, 0], np.array([np.nan, 168.3100]))
+ # Test b phi coefficients
+ np.testing.assert_array_equal(phi_coeffs[:, 1], np.array([np.nan, -1.0752]))
+
+
+@pytest.mark.external_test_data
+def test_get_scattering_thresholds(ancillary_files):
+ """Tests function get_scattering_thresholds."""
+
+ thresholds = get_scattering_thresholds(
+ ancillary_files=ancillary_files,
+ )
+ assert thresholds[(1.0, 5.0)] == 12.0
+ assert thresholds[(5.0, 8.0)] == 10.0
+ 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 d94d118b3d..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,8 +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.kernels import ensure_spice
+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,
)
@@ -23,11 +28,25 @@
TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1"
+@pytest.mark.external_test_data
@pytest.mark.external_kernel
-@ensure_spice
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_calculate_spacecraft_pset(deadtime_datasets):
+def test_calculate_spacecraft_pset(
+ aux_dataset,
+ rates_dataset,
+ mock_goodtimes_dataset,
+ imap_ena_sim_metakernel,
+ use_fake_spin_data_for_time,
+ ancillary_files,
+ mock_spacecraft_pointing_lookups,
+):
"""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)
@@ -55,36 +74,45 @@ def test_calculate_spacecraft_pset(deadtime_datasets):
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": (["epoch"], df["Spin"].values),
+ "quality_scattering": (
+ ["epoch"],
+ np.zeros(len(df["Spin"].values), dtype=np.uint16),
+ ),
+ "quality_outliers": (
+ ["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"},
)
-
- path = imap_module_directory / "tests" / "ultra" / "data" / "l1"
- ancillary = {
- "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",
- }
-
- 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,
- )
+ 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
@@ -92,11 +120,18 @@ def test_calculate_spacecraft_pset(deadtime_datasets):
@pytest.mark.external_test_data
@pytest.mark.external_kernel
-@ensure_spice
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
+def test_calculate_spacecraft_pset_with_cdf(
+ ancillary_files,
+ aux_dataset,
+ rates_dataset,
+ mock_goodtimes_dataset,
+ imap_ena_sim_metakernel,
+ use_fake_spin_data_for_time,
+ mock_spacecraft_pointing_lookups,
+):
"""Tests calculate_spacecraft_pset 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)
df = pd.read_csv(TEST_PATH / "IMAP-Ultra45_r1_L1_V0_shortened.csv")
# Loop over all unique pointing numbers
@@ -107,7 +142,11 @@ def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
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)
@@ -135,30 +174,165 @@ def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
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"] = 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["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")
-
- path = imap_module_directory / "tests" / "ultra" / "data" / "l1"
- ancillary = {
- "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",
- }
-
- spacecraft_pset = calculate_spacecraft_pset(
- dataset,
- xr.Dataset(), # placeholder for extendedspin_dataset
- xr.Dataset(), # placeholder for cullingmask_dataset
- deadtime_datasets["rates"],
- deadtime_datasets["params"],
- "imap_ultra_l1c_45sensor-spacecraftpset",
- ancillary,
- )
+ 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 35c1c93f89..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,17 +174,48 @@ 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)
- l1b_de_dataset_path = TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207_v999.cdf"
+ l1b_de_dataset_path = (
+ 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 [
@@ -164,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
@@ -177,10 +240,15 @@ 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_v999.cdf"
+ l1b_de_dataset_path = (
+ TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207-repoint99999_v999.cdf"
+ )
l1b_de_dataset = load_cdf(l1b_de_dataset_path)
data_dict = {
@@ -190,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
@@ -206,11 +279,16 @@ 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 = TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207_v999.cdf"
+ l1b_de_dataset_path = (
+ TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207-repoint99999_v999.cdf"
+ )
l1b_de_dataset = load_cdf(l1b_de_dataset_path)
data_dict = {
@@ -220,31 +298,41 @@ 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 = TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207_v999.cdf"
+ l1b_de_dataset_path = (
+ TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207-repoint99999_v999"
+ )
l1b_de_dataset = load_cdf(l1b_de_dataset_path)
data_dict = {
@@ -254,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,
)
@@ -269,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
@@ -293,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 083829dbab..3b90564f79 100644
--- a/imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py
+++ b/imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py
@@ -11,28 +11,25 @@
@pytest.fixture
-def kernels(spice_test_data_path):
+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",
"imap_spk_demo.bsp",
]
- kernels = [str(spice_test_data_path / kernel) for kernel in required_kernels]
-
- return kernels
+ with furnish_kernels(required_kernels):
+ yield [str(spice_test_data_path / kernel) for kernel in required_kernels]
@pytest.mark.external_kernel
-def test_get_particle_velocity(spice_test_data_path, kernels):
+def test_get_particle_velocity(spice_test_data_path, furnish_kernels):
"""Tests get_particle_velocity function."""
- spiceypy.furnsh(kernels)
-
pointing_cover = spiceypy.ckcov(
str(spice_test_data_path / "sim_1yr_imap_pointing_frame.bc"),
SpiceFrame.IMAP_DPS.value,
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 b471a536c2..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,12 +1,16 @@
"""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 (
ImapAttitudeUltraFlags,
+ ImapDEScatteringUltraFlags,
ImapHkUltraFlags,
ImapInstrumentUltraFlags,
ImapRatesUltraFlags,
@@ -14,20 +18,61 @@
from imap_processing.ultra.constants import UltraConstants
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."""
@@ -169,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)
@@ -210,7 +271,7 @@ def test_get_pulses(rates_l1_test_path, use_fake_spin_data_for_time):
"spin": df["Spin"],
}
- start_per_spin, stop_per_spin, coin_per_spin = 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"]
@@ -231,6 +292,704 @@ def test_get_pulses(rates_l1_test_path, use_fake_spin_data_for_time):
for i, spin in enumerate(unique_spins):
mask = pulse_dict["spin"] == spin
- assert np.isclose(start_per_spin[i], np.sum(start_pulses_total[mask]))
- assert np.isclose(stop_per_spin[i], np.sum(stop_pulses_total[mask]))
- assert np.isclose(coin_per_spin[i], np.sum(coin_pulses_total[mask]))
+ assert np.isclose(pulses.start_per_spin[i], np.sum(start_pulses_total[mask]))
+ assert np.isclose(pulses.stop_per_spin[i], np.sum(stop_pulses_total[mask]))
+ assert np.isclose(pulses.coin_per_spin[i], np.sum(coin_pulses_total[mask]))
+
+ np.testing.assert_allclose(pulses.start_pulses, start_pulses_total)
+ np.testing.assert_allclose(pulses.stop_pulses, stop_pulses_total)
+ np.testing.assert_allclose(pulses.coin_pulses, coin_pulses_total)
+
+
+@pytest.mark.external_test_data
+def test_flag_scattering(ancillary_files):
+ """Tests flag_scattering function."""
+ tof_energy = np.full(9, 0.5)
+ theta = np.full(9, 30.0)
+ phi = np.full(9, 60.0)
+ quality_flags = np.full(
+ phi.shape, ImapDEScatteringUltraFlags.NONE.value, dtype=np.uint16
+ )
+ flag_scattering(tof_energy, theta, phi, ancillary_files, "ultra45", quality_flags)
+ assert np.all(quality_flags == 0)
+
+ tof_energy = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
+ theta = np.array([1, 2, 50, 50, 50, 60, 70, 80, 90])
+ phi = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90])
+ quality_flags = np.full(
+ phi.shape, ImapDEScatteringUltraFlags.NONE.value, dtype=np.uint16
+ )
+ flag_scattering(tof_energy, theta, phi, ancillary_files, "ultra45", quality_flags)
+ assert np.all(quality_flags == np.array([1, 1, 2, 2, 2, 2, 2, 2, 2]))
+
+
+def test_get_de_rejection_mask():
+ """Tests get_de_rejection_mask function."""
+ quality_scattering = np.array([0, 1, 0, 1, 1, 0, 0, 1, 0])
+ quality_outliers = np.array([0, 0, 1, 0, 1, 0, 1, 0, 0])
+
+ counted = get_de_rejection_mask(quality_scattering, quality_outliers)
+
+ np.testing.assert_array_equal(
+ 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."""
+
+ spins = np.array([0, 0, 0, 1, 1, 2, 2, 2, 2])
+ quality_scattering = np.array([0, 1, 0, 1, 1, 0, 0, 1, 0])
+ quality_outliers = np.array([0, 0, 1, 0, 1, 0, 1, 0, 0])
+
+ counted = count_rejected_events_per_spin(
+ spins, quality_scattering, quality_outliers
+ )
+
+ 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 51ea50145c..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 ImapDEUltraFlags
-from imap_processing.spice.spin import get_spin_data
+from imap_processing.quality_flags import ImapDEOutliersUltraFlags
+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,28 +23,30 @@
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,
+ is_back_tof_valid,
+ is_coin_ph_valid,
)
TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1"
-@pytest.mark.external_test_data
@pytest.fixture
def test_fixture(de_dataset, events_fsw_comparison_theta_0, ancillary_files):
- """Fixture to compute and return yf and related data."""
+ """Fixture to compute and yf and related data."""
# Remove start_type with fill values
de_dataset = de_dataset.where(de_dataset["start_type"] != 255, drop=True)
@@ -104,7 +108,7 @@ def test_get_ph_tof_and_back_positions(test_fixture, ancillary_files):
df_filt, _, _, de_dataset = test_fixture
- ph_tof, _, ph_xb, ph_yb = get_ph_tof_and_back_positions(
+ ph_result = get_ph_tof_and_back_positions(
de_dataset, df_filt.Xf.astype("float").values, "ultra45", ancillary_files
)
@@ -114,10 +118,10 @@ def test_get_ph_tof_and_back_positions(test_fixture, ancillary_files):
selected_rows = df_filt.iloc[ph_indices]
- np.testing.assert_array_equal(ph_xb, selected_rows["Xb"].astype("float"))
- np.testing.assert_array_equal(ph_yb, selected_rows["Yb"].astype("float"))
+ np.testing.assert_array_equal(ph_result.xb, selected_rows["Xb"].astype("float"))
+ np.testing.assert_array_equal(ph_result.yb, selected_rows["Yb"].astype("float"))
np.testing.assert_allclose(
- ph_tof, selected_rows["TOF"].astype("float"), atol=1e-5, rtol=0
+ ph_result.tof, selected_rows["TOF"].astype("float"), atol=1e-5, rtol=0
)
@@ -169,7 +173,7 @@ def test_get_coincidence_positions(test_fixture, ancillary_files):
"""Tests get_coincidence_positions function."""
df_filt, _, _, de_dataset = test_fixture
# Get particle tof (t2).
- _, t2, _, _ = get_ph_tof_and_back_positions(
+ ph_result = get_ph_tof_and_back_positions(
de_dataset, df_filt.Xf.astype("float").values, "ultra45", ancillary_files
)
@@ -181,7 +185,9 @@ def test_get_coincidence_positions(test_fixture, ancillary_files):
rows = df_filt.iloc[indices]
# Get coincidence position and eTOF.
- etof, xc = get_coincidence_positions(de_filtered, t2, "ultra45", ancillary_files)
+ etof, xc = get_coincidence_positions(
+ de_filtered, ph_result.t2, "ultra45", ancillary_files
+ )
np.testing.assert_allclose(xc, rows["Xc"].astype("float"), atol=1e-4, rtol=0)
np.testing.assert_allclose(
@@ -194,7 +200,7 @@ def test_calculate_etof_xc(test_fixture, ancillary_files):
"""Tests calculate_etof_xc function."""
df_filt, _, _, de_dataset = test_fixture
# Get particle tof (t2).
- _, t2, _, _ = get_ph_tof_and_back_positions(
+ ph_result = get_ph_tof_and_back_positions(
de_dataset, df_filt.Xf.astype("float").values, "ultra45", ancillary_files
)
# Filter based on STOP_TYPE.
@@ -217,10 +223,10 @@ def test_calculate_etof_xc(test_fixture, ancillary_files):
# Calculate for Top and Bottom
etof_top, xc_top = calculate_etof_xc(
- de_top, t2[index_top], "ultra45", "TP", ancillary_files
+ de_top, ph_result.t2[index_top], "ultra45", "TP", ancillary_files
)
etof_bottom, xc_bottom = calculate_etof_xc(
- de_bottom, t2[index_bottom], "ultra45", "BT", ancillary_files
+ de_bottom, ph_result.t2[index_bottom], "ultra45", "BT", ancillary_files
)
# Assertions for Top
@@ -262,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,
)
@@ -337,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"]
@@ -353,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)
@@ -391,7 +394,9 @@ def test_get_energy_pulse_height(
test_xb = df_filt["Xb"].astype("float").values
test_yb = df_filt["Yb"].astype("float").values
- quality_flags = np.full(test_xb.shape, ImapDEUltraFlags.NONE.value, dtype=np.uint16)
+ quality_flags = np.full(
+ test_xb.shape, ImapDEOutliersUltraFlags.NONE.value, dtype=np.uint16
+ )
energy, ph_correction = get_energy_pulse_height(
de_dataset["stop_type"].data,
@@ -407,7 +412,9 @@ def test_get_energy_pulse_height(
np.testing.assert_allclose(test_energy.to_numpy(), energy[ph_indices], atol=1e-2)
- flagged_indices = np.nonzero(quality_flags != ImapDEUltraFlags.NONE.value)[0]
+ flagged_indices = np.nonzero(quality_flags != ImapDEOutliersUltraFlags.NONE.value)[
+ 0
+ ]
assert flagged_indices.size == 99
@@ -449,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_proton,
+ np.full(len(UltraConstants.TOFXE_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_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
+ ),
)
@@ -494,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
@@ -636,43 +696,142 @@ 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)
@pytest.mark.external_test_data
-def test_determine_ebin_ph(test_fixture):
+def test_determine_ebin_ph(events_fsw_comparison_theta_0_revised, ancillary_files):
"""Tests determine_ebin_ph function."""
- df_filt, _, _, _ = test_fixture
- df_ph = df_filt[df_filt["StopType"].isin(StopType.PH.value)]
+ df = pd.read_csv(events_fsw_comparison_theta_0_revised)
+ df_filt = df[df["StartType"] != -1]
+ df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
- bin = determine_ebin_pulse_height(
+ ebins = determine_ebin_pulse_height(
df_ph["Energy"].astype("float").to_numpy(),
df_ph["TOF"].astype("float").to_numpy(),
df_ph["r"].astype("float").to_numpy(),
+ df_ph["BackTOFValid"].astype(bool).values,
+ df_ph["CoinPHValid"].astype(bool).values,
+ ancillary_files,
+ )
+
+ valid = (
+ (df_ph["Energy"].astype(float).astype(int) >= 0)
+ & (df_ph["Energy"].astype(float).astype(int) < 2048)
+ & (df_ph["cTOF"].astype(float).astype(int) >= 0)
+ & (df_ph["cTOF"].astype(float).astype(int) < 4096)
+ & (df_ph["BackTOFValid"].astype(float) == 1)
+ & (df_ph["CoinPHValid"].astype(float) == 1)
)
- # TODO: add in bin values.
np.testing.assert_allclose(
- bin, np.full(len(bin), 255, dtype=np.uint8), atol=1e-05, rtol=0
+ ebins[valid], df_ph["ComputedBin"].astype(float).astype(int)[valid], atol=1e-05
)
@pytest.mark.external_test_data
-def test_determine_ebin_ssd(test_fixture):
+def test_determine_ebin_ssd(events_fsw_comparison_theta_0_revised, ancillary_files):
"""Tests determine_ebin_ssd function."""
- df_filt, _, _, _ = test_fixture
+ df = pd.read_csv(events_fsw_comparison_theta_0_revised)
+ df_filt = df[df["StartType"] != -1]
df_ssd = df_filt[df_filt["StopType"].isin(StopType.SSD.value)]
- bin = determine_ebin_ssd(
+ ebins = determine_ebin_ssd(
df_ssd["Energy"].astype("float").to_numpy(),
df_ssd["TOF"].astype("float").to_numpy(),
df_ssd["r"].astype("float").to_numpy(),
+ "ultra45",
+ ancillary_files,
+ )
+
+ valid = (
+ (df_ssd["Energy"].astype(float).astype(int) >= 0)
+ & (df_ssd["Energy"].astype(float).astype(int) < 4096)
+ & (df_ssd["cTOF"].astype(float).astype(int) >= 0)
+ & (df_ssd["cTOF"].astype(float).astype(int) < 2048)
)
- # TODO: add in bin values.
np.testing.assert_allclose(
- bin, np.full(len(bin), 255, dtype=np.uint8), atol=1e-05, rtol=0
+ ebins[valid], df_ssd["ComputedBin"].astype(float).astype(int)[valid], atol=1e-05
)
+
+
+@pytest.mark.external_test_data
+def test_is_back_tof_valid(test_fixture, ancillary_files):
+ """Tests is_back_tof_valid function."""
+ df_filt, _, _, de_dataset = test_fixture
+ df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
+
+ # 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
+def test_is_coin_ph_valid(test_fixture, ancillary_files):
+ """Tests is_coin_ph_valid function."""
+ df_filt, _, _, de_dataset = test_fixture
+ df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])]
+
+ # 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,
+ )
+
+ 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 cbbc75718b..bb8b8d1d40 100644
--- a/imap_processing/tests/ultra/unit/test_ultra_l1c.py
+++ b/imap_processing/tests/ultra/unit/test_ultra_l1c.py
@@ -1,3 +1,6 @@
+from unittest import mock
+
+import astropy_healpix.healpy as hp
import numpy as np
import pandas as pd
import pytest
@@ -6,7 +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.kernels import ensure_spice
+from imap_processing.spice.time import (
+ et_to_met,
+)
from imap_processing.ultra.l1b.ultra_l1b_annotated import (
get_annotated_particle_velocity,
)
@@ -21,6 +26,14 @@
TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1"
+@pytest.fixture
+def fake_spin_data(spice_test_data_path, use_test_spin_data_csv):
+ """Generate fake spin dataframe for testing"""
+ fake_spin_path = spice_test_data_path / "fake_spin_data.csv"
+ use_test_spin_data_csv([fake_spin_path])
+ return fake_spin_path
+
+
@pytest.fixture
def mock_data_l1b_dict():
# Create sample data for the xarray Dataset
@@ -49,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
@@ -93,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(
@@ -126,16 +115,23 @@ 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
-@ensure_spice
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
+def test_calculate_spacecraft_pset_with_cdf(
+ ancillary_files,
+ rates_dataset,
+ aux_dataset,
+ mock_goodtimes_dataset,
+ imap_ena_sim_metakernel,
+ use_fake_spin_data_for_time,
+ mock_spacecraft_pointing_lookups,
+):
"""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)
df = pd.read_csv(TEST_PATH / "IMAP-Ultra45_r1_L1_V0_shortened.csv")
# Select a single pointing number
@@ -143,7 +139,11 @@ def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
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)
@@ -161,6 +161,8 @@ def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
tof_tenths_ns,
)
de_dict["direct_event_velocity"] = v.astype(np.float32)
+ de_dict["quality_scattering"] = np.zeros(len(v), dtype=np.uint16)
+ de_dict["quality_outliers"] = np.zeros(len(v), dtype=np.uint16)
ultra_frame = SpiceFrame.IMAP_ULTRA_45
_, sc_dps_velocity, _ = get_annotated_particle_velocity(
@@ -173,30 +175,36 @@ def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
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"] = 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": xr.Dataset(), # placeholder
- "imap_ultra_l1b_45sensor-cullingmask": xr.Dataset(), # placeholder
- "imap_ultra_45sensor-rates": deadtime_datasets["rates"],
- "imap_ultra_45sensor-params": deadtime_datasets["params"],
- }
-
- 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",
+ "imap_ultra_l1b_45sensor-extendedspin": dataset, # placeholder
+ "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()
@@ -208,22 +216,39 @@ def test_calculate_spacecraft_pset_with_cdf(ancillary_files, deadtime_datasets):
@pytest.mark.external_test_data
@pytest.mark.external_kernel
-@ensure_spice
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_calculate_helio_pset_with_cdf(ancillary_files):
+def test_calculate_helio_pset_with_cdf(
+ ancillary_files,
+ imap_ena_sim_metakernel,
+ 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=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)
@@ -252,28 +277,47 @@ def test_calculate_helio_pset_with_cdf(ancillary_files):
de_dict["velocity_dps_helio"] = helio_dps_velocity
de_dict["energy_heliosphere"] = get_de_energy_kev(helio_dps_velocity, species_bin)
+ 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
- }
-
- 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",
+ "imap_ultra_l1b_45sensor-goodtimes": mock_goodtimes_dataset,
+ "imap_ultra_l1a_45sensor-rates": rates_dataset,
+ "imap_ultra_l1a_45sensor-aux": aux_dataset,
}
-
- output_datasets = ultra_l1c(data_dict, ancillary_files, has_spice=True)
+ 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, "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
new file mode 100644
index 0000000000..217283c570
--- /dev/null
+++ b/imap_processing/tests/ultra/unit/test_ultra_l1c_culling.py
@@ -0,0 +1,128 @@
+"""Tests Culling for ULTRA L1c."""
+
+import astropy_healpix.healpy as hp
+import numpy as np
+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
+
+
+@pytest.mark.external_kernel
+def test_compute_culling_mask(furnish_kernels, spice_test_data_path):
+ """Tests compute_culling_mask function."""
+
+ planet_radii_km = {
+ "EARTH": 6378.137,
+ }
+
+ kernels = [
+ "imap_science_120.tf",
+ "sim_1yr_imap_pointing_frame.bc",
+ "imap_spk_demo.bsp",
+ "imap_sclk_0000.tsc",
+ "naif0012.tls",
+ ]
+
+ keepout_radius_km = 30 * planet_radii_km["EARTH"]
+
+ # Corresponds to 2025-11-28T00:00:00
+ et_start = 817561854.185627
+ 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, spacecraft_pset_quality_flags
+ )
+
+ assert mask.shape[0] == len(et_steps)
+ assert mask.shape[1] == hp.nside2npix(128)
+
+ # Check that some pixels are masked out
+ assert not np.all(mask)
+ assert np.any(mask)
+
+
+@pytest.mark.external_kernel
+def test_compare_sincpt_with_culling_mask_deterministic(furnish_kernels):
+ """Compare culling mask output for the closest-to-Earth pixel with sincpt."""
+
+ with furnish_kernels(
+ [
+ "imap_science_120.tf",
+ "imap_sclk_0000.tsc",
+ "sim_1yr_imap_pointing_frame.bc",
+ "imap_spk_demo.bsp",
+ "earth_latest_high_prec.bpc",
+ "pck00011.tpc",
+ "naif0012.tls",
+ "de440s.bsp",
+ ]
+ ):
+ 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,
+ 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
+ pixel_vecs_dps = np.column_stack(
+ hp.pix2vec(nside, np.arange(hp.nside2npix(nside)), nest=False)
+ )
+ # Find the HEALPix pixel direction closest to the direction from IMAP to Earth
+ closest_idx = np.argmax(np.dot(pixel_vecs_dps, unit_vectors[0]))
+
+ # Transform closest pixel vector to J2000
+ rot_dps_to_j2000 = spiceypy.pxform("IMAP_DPS", "J2000", et[0])
+ pixel_vec_j2000 = np.dot(rot_dps_to_j2000, pixel_vecs_dps[closest_idx])
+
+ with spiceypy.no_found_check():
+ result = spiceypy.sincpt(
+ method="ELLIPSOID",
+ target="EARTH",
+ et=et[0],
+ fixref="IAU_EARTH",
+ abcorr="NONE",
+ obsrvr="IMAP",
+ dref="J2000",
+ dvec=pixel_vec_j2000,
+ )
+
+ assert result[-1] # Check if the ray intersects Earth
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 1afb967ac0..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,33 +1,58 @@
"Tests pointing sets"
+import logging
+from unittest import mock
+
import astropy_healpix.healpy as hp
import numpy as np
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_accepted_pixels,
+)
from imap_processing.ultra.l1c.ultra_l1c_pset_bins import (
build_energy_bins,
- get_deadtime_correction_factors,
+ calculate_exposure_time,
+ get_deadtime_ratios,
+ get_deadtime_ratios_by_spin_phase,
+ get_efficiencies_and_geometric_function,
get_energy_delta_minus_plus,
- get_helio_background_rates,
- get_helio_exposure_times,
- get_helio_sensitivity,
get_sectored_rates,
get_spacecraft_background_rates,
+ get_spacecraft_count_rate_uncertainty,
get_spacecraft_exposure_times,
get_spacecraft_histogram,
- get_spacecraft_sensitivity,
- grid_sensitivity,
- interpolate_sensitivity,
)
BASE_PATH = imap_module_directory / "ultra" / "lookup_tables"
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."""
@@ -46,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] == 0
- assert energy_bin_start[1] == 3.385
- 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], 4.137, atol=1e-4)
- np.testing.assert_allclose(energy_bin_start[-1], 279.810, atol=1e-4)
- np.testing.assert_allclose(energy_bin_end[-1], 341.989, atol=1e-4)
+ 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)
@@ -74,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(
@@ -93,15 +118,11 @@ 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 2 counts are in the third energy bin
+ # Spot check that 2 counts are in the second energy bin
assert np.sum(hist[2, :]) == 2
# Test overlapping energy bins
@@ -110,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):
@@ -125,58 +142,36 @@ def mock_imap_state(time, ref_frame):
return np.array([0, 0, 0, 0, 0, 0])
-def test_get_spacecraft_background_rates():
- """Tests get_background_rates function."""
- background_rates = get_spacecraft_background_rates(nside=128)
- _, energy_midpoints, _ = build_energy_bins()
- assert background_rates.shape == (len(energy_midpoints), hp.nside2npix(128))
-
-
-def test_get_helio_background_rates():
- """Tests get_background_rates function."""
- background_rates = get_helio_background_rates(nside=128)
- _, energy_midpoints, _ = build_energy_bins()
- assert background_rates.shape == (len(energy_midpoints), hp.nside2npix(128))
+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)
-def test_get_sectored_rates():
+def test_get_sectored_rates_manual():
"""Tests get_sectored_rates function."""
-
- # Simulate a test rates dataset.
- epoch = 60
- test_l1a_rates_dataset = xr.Dataset(
+ # 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(
{
- "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)))},
+ "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.hstack([np.arange(10, 20), np.arange(30, 40), np.arange(50, 60)]),
+ 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",
)
- # 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))
+ xr.testing.assert_equal(sectored_rates, expected_sectored_rates)
-def test_get_deadtime_correction_factors():
+def test_get_deadtime_ratios():
"""Tests get_deadtime_correction_factors function."""
# Simulate a test sectored rates dataset.
epoch = 10
@@ -193,144 +188,333 @@ def test_get_deadtime_correction_factors():
"stop_bn": (["epoch"], np.random.randint(0, 5, epoch)),
}
)
- deadtime_correction_factors = get_deadtime_correction_factors(sectored_rates_ds)
+ 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)
-@pytest.mark.external_test_data
-def test_get_spacecraft_exposure_times(deadtime_datasets):
- """Test get_spacecraft_exposure_times function."""
- constant_exposure = (
- TEST_PATH / "imap_ultra_l1c-90sensor-dps-exposure_20250101_v000.csv"
+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
+ num_deadtimes = int(
+ num_spins * 15
+ ) # 15 sectors per spin. One deadtime ratio per sector
+
+ deadtime_ratios = xr.DataArray(
+ np.random.uniform(0.1, 1.0, num_deadtimes), dims=["epoch"]
)
- rates = deadtime_datasets["rates"]
- params = deadtime_datasets["params"]
- df_exposure = pd.read_csv(constant_exposure)
- exposure_pointing = get_spacecraft_exposure_times(df_exposure, rates, params)
- assert exposure_pointing.shape == (196608,)
-
- np.testing.assert_allclose(
- exposure_pointing.values[22684:22686],
- np.array([1.035, 1.035]) * 5760,
- atol=1e-6,
+ 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, 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",
+ return_value=deadtime_ratios * np.nan,
+ ):
+ # Assert value error is raised for NaN values
+ with pytest.raises(
+ ValueError,
+ match="All dead time ratios are NaN, cannot interpolate",
+ ):
+ get_deadtime_ratios_by_spin_phase(
+ sectored_rates_ds, aux_dataset, spin_steps=num_deadtimes
+ )
-@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_get_helio_exposure_times():
- """Tests get_helio_exposure_times function."""
-
- start_time = 829485054.185627
- end_time = 829567884.185627
-
- mid_time = np.average([start_time, end_time])
+@pytest.mark.external_test_data
+def test_get_deadtime_interpolator_no_sectored_rates(ancillary_files, aux_dataset):
+ """Tests get_deadtime_correction_factors function."""
- constant_exposure = (
- TEST_PATH / "imap_ultra_l1c-90sensor-dps-exposure_20250101_v000.csv"
+ 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,
)
- df_exposure = pd.read_csv(constant_exposure)
-
- helio_exposure = get_helio_exposure_times(mid_time, df_exposure)
-
- _, energy_midpoints, _ = build_energy_bins()
-
- nside = 128
- npix = hp.nside2npix(nside)
- assert helio_exposure.shape == (len(energy_midpoints), npix)
-
- total_input = np.sum(df_exposure["Exposure Time"].values)
- total_output = np.sum(helio_exposure[23, :])
+ 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)
- assert np.allclose(total_input, total_output, atol=1e-6)
+@pytest.mark.external_kernel
+def test_apply_deadtime_correction(
+ imap_ena_sim_metakernel, ancillary_files, spun_index_data
+):
+ """Tests apply_deadtime_correction function."""
+ 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)
-@pytest.mark.external_test_data
-def test_get_spacecraft_sensitivity():
- """Tests get_spacecraft_sensitivity function."""
- # TODO: remove below here with lookup table aux api
- efficiencies = TEST_PATH / "imap_ultra_l1c-90sensor-efficiencies_20250101_v000.csv"
- geometric_function = TEST_PATH / "imap_ultra_l1c-90sensor-gf_20250101_v000.csv"
- df_efficiencies = pd.read_csv(efficiencies)
- df_geometric_function = pd.read_csv(geometric_function)
+@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,
+ )
- sensitivity, energy_vals, right_ascension, declination = get_spacecraft_sensitivity(
- df_efficiencies, df_geometric_function
+ 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.
+ # 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] >= 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)
- assert sensitivity.shape == (df_efficiencies.shape[0], df_efficiencies.shape[1] - 2)
- assert np.array_equal(energy_vals, np.arange(3.0, 80.5, 0.5))
- df_efficiencies_test = pd.DataFrame(
- {"3.0keV": [1.0, 2.0], "3.5keV": [3.0, 4.0], "4.0keV": [5.0, 6.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)
- df_geometric_function_test = pd.DataFrame({"Response": [0.1, 0.2]})
- df_sensitivity_test = df_efficiencies_test.mul(
- df_geometric_function_test["Response"], axis=0
+@pytest.mark.external_test_data
+def test_get_spacecraft_exposure_times(
+ 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."""
+ 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, fwhm_theta, fwhm_phi, thresholds = (
+ calculate_accepted_pixels(
+ spin_phase_steps, mock_theta, mock_phi, ancillary_files, 45
+ )
)
-
- expected_sensitivity = pd.DataFrame(
- {"3.0keV": [0.1, 0.4], "3.5keV": [0.3, 0.8], "4.0keV": [0.5, 1.2]}
+ 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,
)
-
- assert np.allclose(
- df_sensitivity_test.to_numpy(), expected_sensitivity.to_numpy(), atol=1e-6
+ 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(
+ rates_l1_test_path, use_fake_spin_data_for_time, ancillary_files
+):
+ "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))},
)
- expected_result = sensitivity["3.0keV"].values
- result = grid_sensitivity(df_efficiencies, df_geometric_function, 3.0)
-
- assert np.allclose(result, expected_result, atol=1e-5)
+ df = pd.read_csv(rates_l1_test_path)
+
+ rates = {
+ # Stop pulses
+ "stop_tn": df["StopTopNorthCFD"],
+ "stop_bn": df["StopBottomNorthCFD"],
+ "stop_te": df["StopTopEastCFD"],
+ "stop_be": df["StopBottomEastCFD"],
+ "stop_ts": df["StopTopSouthCFD"],
+ "stop_bs": df["StopBottomSouthCFD"],
+ "stop_tw": df["StopTopWestCFD"],
+ "stop_bw": df["StopBottomWestCFD"],
+ # Start pulses
+ "start_rf": df["StartRightFullCFD"],
+ "start_lf": df["StartLeftFullCFD"],
+ # Coincidence pulses
+ "coin_tn": df["CoinTopNorthCFD"],
+ "coin_bn": df["CoinBottomNorthCFD"],
+ "coin_ts": df["CoinTopSouthCFD"],
+ "coin_bs": df["CoinBottomSouthCFD"],
+ # Additional info
+ "shcoarse": df["TimeTag"],
+ "spin": df["Spin"],
+ }
+ energy_bin_edges, _, _ = build_energy_bins()
+ goodtimes_spin_number = np.array([130, 131])
+
+ background_rates = get_spacecraft_background_rates(
+ rates,
+ aux_ds,
+ "ultra45",
+ ancillary_files,
+ energy_bin_edges,
+ goodtimes_spin_number,
+ )
- # Check that out-of-bounds energy returns all FILL values
- result = grid_sensitivity(df_efficiencies, df_geometric_function, 2.5)
- assert np.all(result == -1.0e31)
+ assert background_rates.shape == (len(energy_bin_edges), hp.nside2npix(128))
+ assert np.allclose(background_rates[0, :], np.full((196608,), 6.37052558e-11))
- result = interpolate_sensitivity(df_efficiencies, df_geometric_function)
- assert result.shape == (24, 196608)
+def test_rate_uncertainty():
+ """Tests spacecraft_count_rate_uncertainty function."""
-@pytest.mark.external_test_data
-@pytest.mark.external_kernel
-@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template")
-def test_get_helio_sensitivity(monkeypatch):
- """Test get_helio_sensitivity function."""
-
- # Load test data
- efficiencies = TEST_PATH / "imap_ultra_l1c-90sensor-efficiencies_20250101_v000.csv"
- geometric_function = TEST_PATH / "imap_ultra_l1c-90sensor-gf_20250101_v000.csv"
- df_efficiencies = pd.read_csv(efficiencies)
- df_geometric_function = pd.read_csv(geometric_function)
-
- # Patch spacecraft velocity to be zero
- monkeypatch.setattr(ultra_l1c_pset_bins, "imap_state", mock_imap_state)
-
- # Define time
- start_time = 829485054.185627
- end_time = 829567884.185627
- mid_time = np.average([start_time, end_time])
-
- # Build energy bins and spacecraft-frame sensitivity
- _, energy_midpoints, _ = build_energy_bins()
- sc_sensitivity = []
- for energy in energy_midpoints:
- s = grid_sensitivity(df_efficiencies, df_geometric_function, energy)
- sc_sensitivity.append(s)
- sc_sensitivity = np.stack(sc_sensitivity, axis=1).T # shape: (n_energy_bins, npix)
-
- # Compute helio-frame sensitivity
- helio_sensitivity = get_helio_sensitivity(
- mid_time,
- df_efficiencies,
- df_geometric_function,
+ hist = np.array(
+ [[0.0, 1.0, 4.0], [9.0, 16.0, 25.0], [36.0, 49.0, 64.0], [0.0, 100.0, 121.0]]
)
- # Flatten and compare
- flat_sc = np.nansum(sc_sensitivity, axis=0)
- flat_helio = np.nansum(helio_sensitivity, axis=0)
+ exposure = np.ones_like(hist)
+ uncertainty = get_spacecraft_count_rate_uncertainty(hist, exposure)
+ expected = np.sqrt(hist)
- np.testing.assert_allclose(flat_sc, flat_helio, atol=1e-5)
+ np.testing.assert_allclose(uncertainty, expected, atol=1e-6)
diff --git a/imap_processing/tests/ultra/unit/test_ultra_l2.py b/imap_processing/tests/ultra/unit/test_ultra_l2.py
index b1128acb7e..c5faa01c8c 100644
--- a/imap_processing/tests/ultra/unit/test_ultra_l2.py
+++ b/imap_processing/tests/ultra/unit/test_ultra_l2.py
@@ -7,18 +7,36 @@
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:
@pytest.fixture
def _setup_spice_kernels_list(self, spice_test_data_path, furnish_kernels):
self.required_kernel_names = [
- "imap_science_100.tf",
+ "naif0012.tls",
+ "imap_science_120.tf",
"imap_sclk_0000.tsc",
"sim_1yr_imap_attitude.bc",
"sim_1yr_imap_pointing_frame.bc",
@@ -28,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
@@ -44,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(
@@ -60,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]
@@ -83,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,
],
@@ -118,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,
@@ -131,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:
@@ -150,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,
@@ -162,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(
@@ -174,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(
{
@@ -203,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
@@ -221,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(
@@ -241,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,
@@ -252,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 (
@@ -286,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(
@@ -324,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,
)
@@ -350,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:]:
@@ -372,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
@@ -385,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"
@@ -522,21 +809,251 @@ def test_ultra_l2_descriptor_rectmap(self, mock_data_dict, furnish_kernels):
)
assert "heliospheric frame" in output_map.attrs["Logical_source_description"]
- assert output_map.attrs["Spice_reference_frame"] == "ECLIPJ2000"
+ 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"] == "ECLIPJ2000"
+ 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 3e1f51f860..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,12 +52,10 @@ 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]
DF: float = 3.39 # Distance from slit to foil [mm]
-
# Derived constants
DMIN_PH_CTOF: float = (
Z_DS - (2**0.5) * DF
@@ -79,53 +83,174 @@ class UltraConstants:
CULLING_RPM_MIN = 2.0
CULLING_RPM_MAX = 6.0
- # Thresholds for culling based on counts.
+ # Energy Bounds for culling (keV).
CULLING_ENERGY_BIN_EDGES: ClassVar[list] = [
- 3.385,
- 4.13722222222222,
- 4.13722222222222,
- 5.05660493827161,
- 5.05660493827161,
- 6.18029492455419,
- 6.18029492455419,
- 7.55369379667734,
- 7.55369379667734,
- 9.23229241816119,
- 9.23229241816119,
- 11.2839129555303,
- 11.2839129555303,
- 13.7914491678704,
- 13.7914491678704,
- 16.8562156496194,
- 16.8562156496194,
- 20.6020413495348,
- 20.6020413495348,
- 25.1802727605426,
- 25.1802727605426,
- 30.775888929552,
- 30.775888929552,
- 37.6149753583414,
- 37.6149753583414,
- 45.9738587713061,
- 45.9738587713061,
- 56.1902718315964,
- 56.1902718315964,
- 68.6769989052845,
- 68.6769989052845,
- 83.93855421757,
- 83.93855421757,
- 102.591566265919,
- 102.591566265919,
- 125.38969210279,
- 125.38969210279,
- 153.254068125632,
- 153.254068125632,
- 187.310527709106,
- 187.310527709106,
- 228.93508942224,
- 228.93508942224,
- 279.809553738294,
- 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 d5abbc7170..70ded1e2ac 100644
--- a/imap_processing/ultra/l0/ultra_utils.py
+++ b/imap_processing/ultra/l0/ultra_utils.py
@@ -1,6 +1,6 @@
"""Contains data classes to support Ultra L0 processing."""
-from typing import NamedTuple, Union
+from typing import NamedTuple
class PacketProperties(NamedTuple):
@@ -9,23 +9,21 @@ class PacketProperties(NamedTuple):
apid: list # List of APIDs
logical_source: list # List of logical sources
addition_to_logical_desc: str # Description of the logical source
- width: Union[int, None] # Width of binary data (could be None).
+ width: int | None # Width of binary data (could be None).
# Block, image_planes, pixel_window_rows, and pixel_window_columns are important for
# decompressing the images and a description is available on page 171 of IMAP-Ultra
# Flight Software Specification document (7523-9009_Rev_-.pdf).
- block: Union[int, None] # Number of values in each block (could be None).
- len_array: Union[
- int, None
- ] # Length of the array to be decompressed (could be None).
- mantissa_bit_length: Union[int, None] # used to determine the level of
+ block: int | None # Number of values in each block (could be None).
+ len_array: int | None # Length of the array to be decompressed (could be None).
+ mantissa_bit_length: int | None # used to determine the level of
# precision that can be recovered from compressed data (could be None).
- image_planes: Union[int, None] = None
+ image_planes: int | None = None
# number of images. See table 11 in the FSSD.
- pixel_window_rows: Union[int, None] = None
+ pixel_window_rows: int | None = None
# number of rows in each image. See table 49 in the FSSD.
- pixel_window_columns: Union[int, None] = None
+ pixel_window_columns: int | None = None
# number of columns in each image. See table 49 in the FSSD.
- image_planes_per_packet: Union[int, None] = None
+ image_planes_per_packet: int | None = None
# number of image planes in each packet. See table 52 in the FSSD.
@@ -139,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,
@@ -155,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 b5776ed752..6228f3b257 100644
--- a/imap_processing/ultra/l1a/ultra_l1a.py
+++ b/imap_processing/ultra/l1a/ultra_l1a.py
@@ -1,7 +1,6 @@
"""Generate ULTRA L1a CDFs."""
import logging
-from typing import Optional
import xarray as xr
@@ -44,7 +43,7 @@
def ultra_l1a( # noqa: PLR0912
- packet_file: str, apid_input: Optional[int] = 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.
@@ -55,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
-------
@@ -64,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 = []
@@ -110,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 92e641b274..0000000000
--- a/imap_processing/ultra/l1b/cullingmask.py
+++ /dev/null
@@ -1,87 +0,0 @@
-"""Calculate Culling Mask."""
-
-import numpy as np
-import xarray as xr
-
-from imap_processing.ultra.l1b.quality_flag_filters import 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 QUALITY_FLAG_FILTERS["quality_attitude"])
- )
- == 0
- ) & (
- (
- (
- extendedspin_dataset["quality_ena_rates"]
- & sum(flag.value for flag in 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 85423bbec6..0122f756b8 100644
--- a/imap_processing/ultra/l1b/de.py
+++ b/imap_processing/ultra/l1b/de.py
@@ -4,12 +4,20 @@
import xarray as xr
from imap_processing.cdf.utils import parse_filename_like
-from imap_processing.quality_flags import ImapDEUltraFlags
+from imap_processing.quality_flags import (
+ ImapDEOutliersUltraFlags,
+ 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,
)
+from imap_processing.ultra.l1b.ultra_l1b_culling import flag_scattering
from imap_processing.ultra.l1b.ultra_l1b_extended import (
StopType,
determine_ebin_pulse_height,
@@ -22,25 +30,28 @@
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,
+ is_coin_ph_valid,
)
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.
@@ -49,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
@@ -62,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 = [
@@ -76,7 +89,7 @@ def calculate_de(
"event_type",
"de_event_met",
"phase_angle",
- "spin",
+ "event_id",
]
dataset_keys = [
"coin_type",
@@ -84,13 +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)}
+ {
+ 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]
@@ -100,35 +115,83 @@ 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)
- 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)
+ 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.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8)
+ start_type: np.ndarray = np.full(
+ len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8
+ )
quality_flags = np.full(
- de_dataset["epoch"].shape, ImapDEUltraFlags.NONE.value, dtype=np.uint16
+ de_dataset["epoch"].shape, ImapDEOutliersUltraFlags.NONE.value, dtype=np.uint16
+ )
+
+ scattering_quality_flags = np.full(
+ de_dataset["epoch"].shape,
+ ImapDEScatteringUltraFlags.NONE.value,
+ dtype=np.uint16,
)
xf[valid_indices] = get_front_x_position(
@@ -137,21 +200,27 @@ 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
- tof[ph_indices], t2[ph_indices], xb[ph_indices], yb[ph_indices] = (
- get_ph_tof_and_back_positions(de_dataset, xf, f"ultra{sensor}", ancillary_files)
+ ph_result = get_ph_tof_and_back_positions(
+ de_dataset, xf, f"ultra{sensor}", ancillary_files
)
+ tof[ph_indices] = ph_result.tof
+ t2[ph_indices] = ph_result.t2
+ xb[ph_indices] = ph_result.xb
+ yb[ph_indices] = ph_result.yb
d[ph_indices], yf[ph_indices] = get_front_y_position(
de_dataset["start_type"].data[ph_indices], yb[ph_indices], ancillary_files
)
@@ -174,16 +243,46 @@ def calculate_de(
(xb[ph_indices], yb[ph_indices]),
d[ph_indices],
)
- e_bin[ph_indices] = determine_ebin_pulse_height(
- energy[ph_indices], tof[ph_indices], r[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_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_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],
+ r[ph_indices],
+ backtofvalid,
+ 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"
)
@@ -211,11 +310,13 @@ def calculate_de(
d[ssd_indices],
)
e_bin[ssd_indices] = determine_ebin_ssd(
- energy[ssd_indices], tof[ssd_indices], r[ssd_indices]
- )
- species_bin[ssd_indices] = determine_species(
- tof[ssd_indices], r[ssd_indices], "SSD"
+ energy[ssd_indices],
+ tof[ssd_indices],
+ r[ssd_indices],
+ f"ultra{sensor}",
+ ancillary_files,
)
+ 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"
)
@@ -237,45 +338,71 @@ def calculate_de(
de_dict["phi"] = phi
de_dict["theta"] = theta
- v, vhat, r = get_de_velocity(
- (de_dict["x_front"], de_dict["y_front"]),
- (de_dict["x_back"], de_dict["y_back"]),
- de_dict["front_back_distance"],
- de_dict["tof_start_stop"],
+ velocities[valid_indices], v_hat[valid_indices], r_hat[valid_indices] = (
+ get_de_velocity(
+ (de_dict["x_front"][valid_indices], de_dict["y_front"][valid_indices]),
+ (de_dict["x_back"][valid_indices], de_dict["y_back"][valid_indices]),
+ de_dict["front_back_distance"][valid_indices],
+ de_dict["tof_start_stop"][valid_indices],
+ )
)
- de_dict["direct_event_velocity"] = v.astype(np.float32)
- de_dict["direct_event_unit_velocity"] = vhat.astype(np.float32)
- de_dict["direct_event_unit_position"] = r.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)
- de_dict["tof_energy"] = get_de_energy_kev(v, species_bin)
+ tof_energy[valid_indices] = get_de_energy_kev(
+ 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,
@@ -286,24 +413,66 @@ 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(
- ancillary_files,
- "l1b-sensor-gf-blades",
de_dict["phi"],
de_dict["theta"],
quality_flags,
+ ancillary_files,
+ "l1b-sensor-gf-blades",
)
de_dict["geometric_factor_noblades"] = get_geometric_factor(
- ancillary_files,
- "l1b-sensor-gf-noblades",
de_dict["phi"],
de_dict["theta"],
quality_flags,
+ ancillary_files,
+ "l1b-sensor-gf-noblades",
)
- de_dict["quality_fov"] = quality_flags
+
+ de_dict["quality_outliers"] = quality_flags
+ flag_scattering(
+ de_dict["tof_energy"],
+ de_dict["theta"],
+ de_dict["phi"],
+ ancillary_files,
+ sensor,
+ scattering_quality_flags,
+ )
+ de_dict["quality_scattering"] = scattering_quality_flags
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 b33b13c677..8fdd394999 100644
--- a/imap_processing/ultra/l1b/extendedspin.py
+++ b/imap_processing/ultra/l1b/extendedspin.py
@@ -2,22 +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:
@@ -28,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
@@ -40,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(
@@ -57,39 +74,182 @@ 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.
- start_per_spin, stop_per_spin, coin_per_spin = 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.
+ rejected_counts = count_rejected_events_per_spin(
+ de_dataset["spin"].values,
+ 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
+
+ # 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
- # TODO: this will be used to track rejected events in each
- # spin based on quality flags in de l1b data.
- extendedspin_dict["rejected_events_per_spin"] = np.full_like(
- spin, FILLVAL_UINT16, dtype=np.uint16
- )
-
+ 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 8960b0382b..fb9dad25c8 100644
--- a/imap_processing/ultra/l1b/lookup_utils.py
+++ b/imap_processing/ultra/l1b/lookup_utils.py
@@ -1,12 +1,17 @@
"""Contains tools for lookup tables for l1b."""
+import logging
+
import numpy as np
import numpy.typing as npt
import pandas as pd
import xarray as xr
from numpy.typing import NDArray
-from imap_processing.quality_flags import ImapDEUltraFlags
+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,27 +225,32 @@ 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
-def get_geometric_factor(
+def load_geometric_factor_tables(
ancillary_files: dict,
filename: str,
- phi: NDArray,
- theta: NDArray,
- quality_flag: NDArray,
-) -> tuple[NDArray, NDArray]:
+) -> dict:
"""
- Lookup table for geometric factor using nearest neighbor.
+ Lookup tables for geometric factor.
Parameters
----------
@@ -248,17 +258,11 @@ def get_geometric_factor(
Ancillary files.
filename : str
Name of the file in ancillary_files to use.
- phi : NDArray
- Azimuth angles in degrees.
- theta : NDArray
- Elevation angles in degrees.
- quality_flag : NDArray
- Quality flag to set when geometric factor is zero.
Returns
-------
- geometric_factor : NDArray
- Geometric factor.
+ geometric_factor_tables : dict
+ Geometric factor lookup tables.
"""
gf_table = pd.read_csv(
ancillary_files[filename], header=None, skiprows=6, nrows=301
@@ -270,28 +274,211 @@ def get_geometric_factor(
ancillary_files[filename], header=None, skiprows=610, nrows=301
).to_numpy(dtype=float)
+ return {
+ "gf_table": gf_table,
+ "theta_table": theta_table,
+ "phi_table": phi_table,
+ }
+
+
+def get_geometric_factor(
+ phi: NDArray,
+ theta: NDArray,
+ quality_flag: NDArray,
+ ancillary_files: dict | None = None,
+ filename: str | None = None,
+ geometric_factor_tables: dict | None = None,
+) -> tuple[NDArray, NDArray]:
+ """
+ Lookup table for geometric factor using nearest neighbor.
+
+ Parameters
+ ----------
+ phi : NDArray
+ Azimuth angles in degrees.
+ theta : NDArray
+ Elevation angles in degrees.
+ quality_flag : NDArray
+ Quality flag to set when geometric factor is zero.
+ ancillary_files : dict[Path], optional
+ Ancillary files.
+ filename : str, optional
+ Name of the file in ancillary_files to use.
+ geometric_factor_tables : dict, optional
+ Preloaded geometric factor lookup tables. If not provided, will load.
+
+ Returns
+ -------
+ geometric_factor : NDArray
+ Geometric factor.
+ """
+ if geometric_factor_tables is None:
+ if ancillary_files is None or filename is None:
+ raise ValueError(
+ "ancillary_files and filename must be provided if "
+ "geometric_factor_tables is not supplied."
+ )
+ geometric_factor_tables = load_geometric_factor_tables(
+ ancillary_files, filename
+ )
# Assume uniform grids: extract 1D arrays from first row/col
- theta_vals = theta_table[0, :] # columns represent theta
- phi_vals = phi_table[:, 0] # rows represent phi
+ theta_vals = geometric_factor_tables["theta_table"][0, :] # columns represent theta
+ phi_vals = geometric_factor_tables["phi_table"][:, 0] # rows represent phi
# Find nearest index in table for each input value
phi_idx = np.abs(phi_vals[:, None] - phi).argmin(axis=0)
theta_idx = np.abs(theta_vals[:, None] - theta).argmin(axis=0)
# Fetch geometric factor values at nearest (phi, theta) pairs
- geometric_factor = gf_table[phi_idx, theta_idx]
+ geometric_factor = geometric_factor_tables["gf_table"][phi_idx, theta_idx]
+
+ outside_fov = ~is_inside_fov(np.deg2rad(theta), np.deg2rad(phi))
+ quality_flag[outside_fov] |= ImapDEOutliersUltraFlags.FOV.value
+
+ return geometric_factor
+
+
+def load_scattering_lookup_tables(ancillary_files: dict, instrument_id: int) -> dict:
+ """
+ Load scattering coefficient lookup tables for the specified instrument.
+
+ Parameters
+ ----------
+ ancillary_files : dict
+ Ancillary files.
+ instrument_id : int
+ Instrument ID, either 45 or 90.
+
+ Returns
+ -------
+ dict
+ Dictionary containing arrays for theta_grid, phi_grid, a_theta, g_theta,
+ a_phi, g_phi.
+ """
+ # TODO remove the line below when the 45 sensor scattering coefficients are
+ # delivered.
+ instrument_id = 90
+ 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)
+ phi_grid = pd.read_csv(
+ ancillary_files[descriptor], header=None, skiprows=249, nrows=241
+ ).to_numpy(dtype=float)
+ a_theta = pd.read_csv(
+ ancillary_files[descriptor], header=None, skiprows=491, nrows=241
+ ).to_numpy(dtype=float)
+ g_theta = pd.read_csv(
+ ancillary_files[descriptor], header=None, skiprows=733, nrows=241
+ ).to_numpy(dtype=float)
+ a_phi = pd.read_csv(
+ ancillary_files[descriptor], header=None, skiprows=975, nrows=241
+ ).to_numpy(dtype=float)
+ g_phi = pd.read_csv(
+ ancillary_files[descriptor], header=None, skiprows=1217, nrows=241
+ ).to_numpy(dtype=float)
+ return {
+ "theta_grid": theta_grid,
+ "phi_grid": phi_grid,
+ "a_theta": a_theta,
+ "g_theta": g_theta,
+ "a_phi": a_phi,
+ "g_phi": g_phi,
+ }
+
+
+def get_scattering_coefficients(
+ theta: NDArray,
+ phi: NDArray,
+ lookup_tables: dict | None = None,
+ ancillary_files: dict | None = None,
+ instrument_id: int | None = None,
+) -> tuple[NDArray, NDArray]:
+ """
+ Get a and g coefficients for theta and phi to compute scattering FWHM.
- phi_rad = np.deg2rad(phi)
- numerator = 5.0 * np.cos(phi_rad)
- denominator = 1 + 2.80 * np.cos(phi_rad)
+ Parameters
+ ----------
+ theta : NDArray
+ Elevation angles in degrees.
+ phi : NDArray
+ Azimuth angles in degrees.
+ lookup_tables : dict, optional
+ Preloaded lookup tables. If not provided, will load using ancillary_files and
+ instrument_id.
+ ancillary_files : dict, optional
+ Ancillary files, required if lookup_tables is not provided.
+ instrument_id : int, optional
+ Instrument ID, required if lookup_tables is not provided.
+
+ Returns
+ -------
+ tuple
+ Scattering a and g values corresponding to the given theta and phi values.
+ """
+ if lookup_tables is None:
+ if ancillary_files is None or instrument_id is None:
+ raise ValueError(
+ "ancillary_files and instrument_id must be provided if lookup_tables "
+ "is not supplied."
+ )
+ lookup_tables = load_scattering_lookup_tables(ancillary_files, instrument_id)
+
+ theta_grid = lookup_tables["theta_grid"]
+ phi_grid = lookup_tables["phi_grid"]
+ a_theta = lookup_tables["a_theta"]
+ g_theta = lookup_tables["g_theta"]
+ a_phi = lookup_tables["a_phi"]
+ g_phi = lookup_tables["g_phi"]
+
+ theta_vals = theta_grid[0, :] # columns represent theta
+ phi_vals = phi_grid[:, 0] # rows represent phi
+
+ phi_idx = np.abs(phi_vals[:, None] - phi).argmin(axis=0)
+ theta_idx = np.abs(theta_vals[:, None] - theta).argmin(axis=0)
+
+ a_theta_val = a_theta[phi_idx, theta_idx]
+ g_theta_val = g_theta[phi_idx, theta_idx]
+ a_phi_val = a_phi[phi_idx, theta_idx]
+ g_phi_val = g_phi[phi_idx, theta_idx]
+
+ return np.column_stack([a_theta_val, g_theta_val]), np.column_stack(
+ [a_phi_val, g_phi_val]
+ )
+
+
+def is_inside_fov(theta: np.ndarray, phi: np.ndarray) -> np.ndarray:
+ """
+ Determine angles in the field of view (FOV).
+
+ This function is used in the deadtime correction to determine whether a given
+ (theta, phi) angle is within the instrument's Field of View (FOV).
+ Only pixels inside the FOV are considered for time accumulation. The FOV boundary
+ is defined by equation 19 in the Ultra Algorithm Document.
+
+ Parameters
+ ----------
+ theta : np.ndarray
+ Elevation angles in radians.
+ phi : np.ndarray
+ Azimuth angles in radians.
+
+ Returns
+ -------
+ numpy.ndarray
+ Boolean array indicating if the angle is in the FOV, False otherwise.
+ """
+ numerator = 5.0 * np.cos(phi)
+ denominator = 1.0 + 2.80 * np.cos(phi)
# Equation 19 in the Ultra Algorithm Document.
- theta_nom = np.arctan(numerator / denominator)
- theta_nom = np.rad2deg(theta_nom)
+ theta_nom = np.arctan(numerator / denominator) - np.radians(
+ UltraConstants.FOV_THETA_OFFSET_DEG
+ )
- outside_fov = np.abs(theta) > theta_nom
- quality_flag[outside_fov] |= ImapDEUltraFlags.FOV.value
+ theta_check = np.abs(theta) <= np.abs(theta_nom)
+ phi_check = np.abs(phi) <= np.radians(UltraConstants.FOV_PHI_LIMIT_DEG)
- return geometric_factor
+ return theta_check & phi_check
def get_ph_corrected(
@@ -343,8 +530,161 @@ def get_ph_corrected(
# Flag where clamping occurred
flagged_mask = (xlut != xlut_clamped) | (ylut != ylut_clamped)
- quality_flag[flagged_mask] |= ImapDEUltraFlags.PHCORR.value
+ quality_flag[flagged_mask] |= ImapDEOutliersUltraFlags.PHCORR.value
ph_correction = ph_correct_array[xlut_clamped, ylut_clamped]
return ph_correction, quality_flag
+
+
+def get_ebins(
+ lut: str,
+ energy: NDArray,
+ ctof: NDArray,
+ ebins: NDArray,
+ ancillary_files: dict,
+) -> NDArray:
+ """
+ Get energy bins from the lookup table.
+
+ Parameters
+ ----------
+ lut : str
+ Lookup table name, e.g., "l1b-tofxpht".
+ energy : NDArray
+ Energy from the event (keV).
+ ctof : NDArray
+ Corrected TOF (tenths of a ns).
+ ebins : NDArray
+ Energy bins to fill with values.
+ ancillary_files : dict[Path]
+ Ancillary files.
+
+ Returns
+ -------
+ ebins : NDArray
+ Energy bins from the lookup table.
+ """
+ with open(ancillary_files[lut]) as f:
+ all_lines = f.readlines()
+ pixel_text = "".join(all_lines[4:])
+
+ lut_array = np.fromstring(pixel_text, sep=" ", dtype=int).reshape((2048, 4096))
+ # Note that the LUT is indexed [energy, ctof] for l1b-tofxph
+ # and [ctof, energy] for everything else.
+ if lut == "l1b-tofxph":
+ energy_lookup = (2048 - np.floor(energy)).astype(int)
+ ctof_lookup = np.floor(ctof).astype(int)
+ valid = (
+ (energy_lookup >= 0)
+ & (energy_lookup < 2048)
+ & (ctof_lookup >= 0)
+ & (ctof_lookup < 4096)
+ )
+ ebins[valid] = lut_array[energy_lookup[valid], ctof_lookup[valid]]
+ else:
+ energy_lookup = np.floor(energy).astype(int)
+ ctof_lookup = (2048 - np.floor(ctof)).astype(int)
+ valid = (
+ (energy_lookup >= 0)
+ & (energy_lookup < 4096)
+ & (ctof_lookup >= 0)
+ & (ctof_lookup < 2048)
+ )
+ ebins[valid] = lut_array[ctof_lookup[valid], energy_lookup[valid]]
+
+ return ebins
+
+
+def get_scattering_thresholds(ancillary_files: dict) -> dict:
+ """
+ Load scattering culling thresholds as a function of energy from a lookup table.
+
+ Parameters
+ ----------
+ ancillary_files : dict[Path]
+ Ancillary files.
+
+ Returns
+ -------
+ threshold_dict
+ Dictionary containing energy ranges and the corresponding scattering culling
+ threshold.
+ """
+ # Culling FWHM Scattering values as a function of energy.
+ thresholds = pd.read_csv(
+ ancillary_files["l1b-scattering-thresholds-per-energy"], header=None, skiprows=1
+ ).to_numpy(dtype=np.float64)
+ # The first two columns represent the energy range (min, max) in keV, and the
+ # value is the FWHM scattering threshold in degrees
+ 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 3e6585f128..faa3921a58 100644
--- a/imap_processing/ultra/l1b/quality_flag_filters.py
+++ b/imap_processing/ultra/l1b/quality_flag_filters.py
@@ -2,13 +2,40 @@
from imap_processing.quality_flags import (
FlagNameMixin,
+ ImapDEOutliersUltraFlags,
+ ImapDEScatteringUltraFlags,
ImapRatesUltraFlags,
)
-QUALITY_FLAG_FILTERS: dict[str, list[FlagNameMixin]] = {
- "quality_attitude": [],
+SPIN_QUALITY_FLAG_FILTERS: dict[str, list[FlagNameMixin]] = {
+ "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,
+ 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 9f591c507c..3ec5c2a9b0 100644
--- a/imap_processing/ultra/l1b/ultra_l1b_culling.py
+++ b/imap_processing/ultra/l1b/ultra_l1b_culling.py
@@ -1,26 +1,56 @@
"""Culls Events for ULTRA L1b."""
import logging
+from collections import namedtuple
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 (
ImapAttitudeUltraFlags,
+ ImapDEScatteringUltraFlags,
ImapHkUltraFlags,
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,
+ 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.
+RateResult = namedtuple(
+ "RateResult",
+ [
+ "unique_spins",
+ "start_per_spin",
+ "stop_per_spin",
+ "coin_per_spin",
+ "start_pulses",
+ "stop_pulses",
+ "coin_pulses",
+ ],
+)
+
def get_energy_histogram(
spin_number: NDArray, energy: NDArray
@@ -51,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(
@@ -109,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
@@ -230,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(
@@ -245,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
@@ -256,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(
@@ -293,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"),
@@ -304,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
@@ -320,99 +348,36 @@ 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):
- # 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) -> tuple[NDArray, NDArray, NDArray]:
+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
Total stop pulses per spin.
coin_per_spin : NDArray
Total coincidence pulses per spin.
+ start_pulses : NDArray
+ Total start pulses.
+ stop_pulses : NDArray
+ Total stop pulses.
+ 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(
@@ -448,4 +413,1010 @@ def get_pulses_per_spin(rates: xr.Dataset) -> tuple[NDArray, NDArray, NDArray]:
stop_per_spin = np.bincount(spin_idx, weights=stop_pulses)
coin_per_spin = np.bincount(spin_idx, weights=coin_pulses)
- return start_per_spin, stop_per_spin, coin_per_spin
+ return RateResult(
+ unique_spins=unique_spins,
+ start_per_spin=start_per_spin,
+ stop_per_spin=stop_per_spin,
+ coin_per_spin=coin_per_spin,
+ start_pulses=start_pulses,
+ stop_pulses=stop_pulses,
+ coin_pulses=coin_pulses,
+ )
+
+
+def flag_scattering(
+ tof_energy: NDArray,
+ theta: NDArray,
+ phi: NDArray,
+ ancillary_files: dict,
+ sensor: str,
+ quality_flags: NDArray,
+) -> None:
+ """
+ Flag events where either theta or phi FWHM exceed the threshold or equal nan.
+
+ Parameters
+ ----------
+ tof_energy : NDArray
+ TOF energy for each event in keV.
+ theta : NDArray
+ Elevation angles in degrees.
+ phi : NDArray
+ Azimuth angles in degrees.
+ ancillary_files : dict[Path]
+ Ancillary files.
+ sensor : str
+ Sensor name: "ultra45" or "ultra90".
+ quality_flags : NDArray
+ 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.
+ # Returns a_theta_val, g_theta_val, a_phi_val, g_phi_val
+ theta_coeffs, phi_coeffs = get_scattering_coefficients(
+ theta[event_mask],
+ phi[event_mask],
+ lookup_tables=None,
+ ancillary_files=ancillary_files,
+ instrument_id=int(sensor[-2:]),
+ )
+ # FWHM_PHI = A_PHI * E^G_PHI
+ # FWHM_THETA = A_THETA * E^G_THETA
+ # 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
+ )
+
+ theta_exceeds = fwhm_theta > threshold
+ phi_exceeds = fwhm_phi > threshold
+ either_exceeds = theta_exceeds | phi_exceeds
+
+ # Set flags for events where either theta or phi FWHM exceed the threshold
+ quality_flags[np.where(event_mask)[0][either_exceeds]] |= (
+ ImapDEScatteringUltraFlags.ABOVE_THRESHOLD.value
+ )
+
+
+def get_de_rejection_mask(
+ quality_scattering: NDArray,
+ quality_outliers: NDArray,
+ reject_scattering: bool = True,
+) -> NDArray:
+ """
+ Create boolean mask where event is rejected due to relevant flags.
+
+ Parameters
+ ----------
+ quality_scattering : NDArray
+ Quality scattering flags.
+ quality_outliers : NDArray
+ Quality outliers flags.
+ reject_scattering : bool
+ Whether to reject based on scattering flags.
+
+ Returns
+ -------
+ rejected : NDArray
+ Rejected events where True = rejected.
+ """
+ # Bitmasks from the DE_QUALITY_FLAG_FILTERS
+ scattering_mask = sum(
+ flag.value for flag in DE_QUALITY_FLAG_FILTERS["quality_scattering"]
+ )
+ 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
+
+ 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
+
+
+def count_rejected_events_per_spin(
+ spins: NDArray, quality_scattering: NDArray, quality_outliers: NDArray
+) -> NDArray:
+ """
+ Count rejected events per spin based on DE_QUALITY_FLAG_FILTERS.
+
+ Parameters
+ ----------
+ spins : NDArray
+ Spins in which each direct event is within.
+ quality_scattering : NDArray
+ Quality scattering flags.
+ quality_outliers : NDArray
+ Quality outliers flags.
+
+ Returns
+ -------
+ rejected_counts : NDArray
+ Rejected counts per spin.
+ """
+ # Boolean mask where event is rejected due to relevant flags
+ rejected = get_de_rejection_mask(quality_scattering, quality_outliers)
+
+ # Unique spin numbers
+ unique_spins = np.unique(spins)
+
+ # Count rejected events per spin
+ rejected_counts = np.array(
+ [np.count_nonzero(rejected[spins == spin]) for spin in unique_spins], dtype=int
+ )
+
+ 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 4b31d1bcdf..78da8bd242 100644
--- a/imap_processing/ultra/l1b/ultra_l1b_extended.py
+++ b/imap_processing/ultra/l1b/ultra_l1b_extended.py
@@ -2,20 +2,24 @@
# TODO: Come back and add in FSW logic.
import logging
+from collections import namedtuple
from enum import Enum
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,
get_back_position,
+ get_ebins,
get_energy_efficiencies,
get_energy_norm,
get_image_params,
@@ -26,6 +30,10 @@
logger = logging.getLogger(__name__)
+FILLVAL_UINT8 = 255
+FILLVAL_FLOAT32 = -1.0e31
+FILLVAL_FLOAT64 = -1.0e31
+
class StartType(Enum):
"""Start Type: 1=Left, 2=Right."""
@@ -50,6 +58,9 @@ class CoinType(Enum):
Bottom = 2
+PHTOFResult = namedtuple("PHTOFResult", ["tof", "t2", "xb", "yb", "tofx", "tofy"])
+
+
def get_front_x_position(
start_type: ndarray, start_position_tdc: ndarray, sensor: str, ancillary_files: dict
) -> ndarray:
@@ -160,8 +171,8 @@ def get_front_y_position(
def get_ph_tof_and_back_positions(
- de_dataset: xarray.Dataset, xf: np.ndarray, sensor: str, ancillary_files: dict
-) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
+ de_dataset: xr.Dataset, xf: np.ndarray, sensor: str, ancillary_files: dict
+) -> PHTOFResult:
"""
Calculate back xb, yb position and tof.
@@ -196,6 +207,10 @@ def get_ph_tof_and_back_positions(
Back positions in x direction (hundredths of a millimeter).
yb : np.array
Back positions in y direction (hundredths of a millimeter).
+ tofx : np.array
+ X front position tof offset (tenths of a nanosecond).
+ tofy : np.array
+ Y front position tof offset (tenths of a nanosecond).
"""
indices = np.nonzero(
np.isin(de_dataset["stop_type"], [StopType.Top.value, StopType.Bottom.value])
@@ -278,7 +293,7 @@ def get_ph_tof_and_back_positions(
stop_type_bottom
] / 10 * get_image_params("XFTTOF", sensor, ancillary_files)
- return tof, t2, xb, yb
+ return PHTOFResult(tof=tof, t2=t2, xb=xb, yb=yb, tofx=tofx, tofy=tofy)
def get_path_length(
@@ -311,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.
@@ -341,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
@@ -365,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,
@@ -419,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,
@@ -465,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,
@@ -520,30 +535,31 @@ 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] = np.nan # used as fillvals
- v_y[tof < 0] = np.nan
- v_z[tof < 0] = np.nan
+ v_x[tof < 0] = FILLVAL_FLOAT32 # used as fillvals
+ v_y[tof < 0] = FILLVAL_FLOAT32
+ v_z[tof < 0] = FILLVAL_FLOAT32
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.
@@ -577,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]
@@ -601,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.
@@ -611,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
-------
@@ -621,14 +641,26 @@ def get_de_energy_kev(v: np.ndarray, species: np.ndarray) -> NDArray:
# Compute the sum of squares.
v2 = np.sum(vv**2, axis=1)
- index_hydrogen = np.where(species == 1)
- energy = np.full_like(v2, np.nan)
+ # Only compute where species == 1 and v is valid
+ index_hydrogen = species == 1
+ valid_velocity = np.isfinite(v2)
+ valid_mask = index_hydrogen & valid_velocity
+
+ energy = np.full_like(v2, FILLVAL_FLOAT32)
# TODO: we will calculate the energies of the different species here.
# 1/2 mv^2 in Joules, convert to keV
- energy[index_hydrogen] = (
- 0.5 * UltraConstants.MASS_H * v2[index_hydrogen] * UltraConstants.J_KEV
+ 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
@@ -677,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
@@ -692,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]),
@@ -701,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]),
@@ -732,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.
@@ -762,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
@@ -811,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
@@ -820,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).
@@ -847,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
@@ -889,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):
- # 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(
@@ -1030,8 +1106,11 @@ def interpolate_fwhm(
)
# Note: will return nan for those out-of-bounds inputs.
- phi_interp = interp_phi((energy, phi_inst))
- theta_interp = interp_theta((energy, theta_inst))
+ phi_vals = interp_phi((energy, phi_inst))
+ theta_vals = interp_theta((energy, theta_inst))
+
+ phi_interp = np.where(np.isnan(phi_vals), FILLVAL_FLOAT32, phi_vals)
+ theta_interp = np.where(np.isnan(theta_vals), FILLVAL_FLOAT32, theta_vals)
return phi_interp, theta_interp
@@ -1069,8 +1148,8 @@ def get_fwhm(
theta_interp : NDArray
Interpolated theta FWHM values.
"""
- phi_interp = np.full_like(phi_inst, np.nan, dtype=np.float64)
- theta_interp = np.full_like(theta_inst, np.nan, dtype=np.float64)
+ phi_interp = np.full_like(phi_inst, FILLVAL_FLOAT64, dtype=np.float64)
+ theta_interp = np.full_like(theta_inst, FILLVAL_FLOAT64, dtype=np.float64)
lt_table = get_angular_profiles("left", sensor, ancillary_files)
rt_table = get_angular_profiles("right", sensor, ancillary_files)
@@ -1089,29 +1168,32 @@ def get_fwhm(
return phi_interp, theta_interp
-def get_efficiency(
- energy: NDArray, phi_inst: NDArray, theta_inst: NDArray, ancillary_files: dict
-) -> NDArray:
+def get_efficiency_interpolator(
+ ancillary_files: dict,
+ sensor: str,
+) -> tuple[RegularGridInterpolator, tuple, tuple, tuple]:
"""
- Interpolate efficiency values for each event.
+ Return a callable function that interpolates efficiency values for each event.
Parameters
----------
- energy : NDArray
- Energy values for each event.
- phi_inst : NDArray
- Instrument-frame azimuth angle for each event.
- theta_inst : NDArray
- Instrument-frame elevation angle for each event.
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())
@@ -1122,19 +1204,66 @@ def get_efficiency(
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),
efficiency_grid,
bounds_error=False,
- fill_value=np.nan,
+ fill_value=FILLVAL_FLOAT32,
)
+ return interpolator, theta_min_max, phi_min_max, energy_min_max
+
+
+def get_efficiency(
+ energy: NDArray,
+ phi_inst: NDArray,
+ theta_inst: NDArray,
+ ancillary_files: dict,
+ sensor: str,
+ interpolator: RegularGridInterpolator = None,
+) -> np.ndarray:
+ """
+ Return interpolated efficiency values for each event.
+
+ Parameters
+ ----------
+ energy : NDArray
+ Energy values for each event.
+ phi_inst : NDArray
+ Instrument-frame azimuth angle for each event.
+ theta_inst : NDArray
+ 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.
+
+ Returns
+ -------
+ efficiency : NDArray
+ Interpolated efficiency values.
+ """
+ if not interpolator:
+ interpolator, _, _, _ = get_efficiency_interpolator(ancillary_files, sensor)
+
return interpolator((theta_inst, phi_inst, energy))
def determine_ebin_pulse_height(
- energy: np.ndarray, tof: np.ndarray, path_length: np.ndarray
+ energy: NDArray,
+ tof: NDArray,
+ path_length: NDArray,
+ backtofvalid: NDArray,
+ coinphvalid: NDArray,
+ ancillary_files: dict,
) -> NDArray:
"""
Determine the species for pulse-height events.
@@ -1152,12 +1281,18 @@ def determine_ebin_pulse_height(
Parameters
----------
- energy : np.ndarray
+ energy : NDArray
Energy from the PH event (keV).
- tof : np.ndarray
+ tof : NDArray
Time of flight of the PH event (tenths of a nanosecond).
- path_length : np.ndarray
+ path_length : NDArray
Path length (r) (hundredths of a millimeter).
+ backtofvalid : NDArray
+ Boolean array indicating if the back TOF is valid.
+ coinphvalid : NDArray
+ Boolean array indicating if the Coincidence PH is valid.
+ ancillary_files : dict
+ Ancillary files containing the lookup tables.
Returns
-------
@@ -1166,15 +1301,22 @@ def determine_ebin_pulse_height(
"""
# PH event TOF normalization to Z axis
ctof, _ = get_ctof(tof, path_length, type="PH")
- # TODO: need lookup tables
- # placeholder
- ebin = np.full(len(ctof), 255, dtype=np.uint8)
- return ebin
+ ebins = np.full(path_length.shape, FILLVAL_UINT8, dtype=np.uint8)
+ valid = backtofvalid & coinphvalid
+ ebins[valid] = get_ebins(
+ "l1b-tofxph", energy[valid], ctof[valid], ebins[valid], ancillary_files
+ )
+
+ return ebins
def determine_ebin_ssd(
- energy: np.ndarray, tof: np.ndarray, path_length: np.ndarray
+ energy: NDArray,
+ tof: NDArray,
+ path_length: NDArray,
+ sensor: str,
+ ancillary_files: dict,
) -> NDArray:
"""
Determine the species for SSD events.
@@ -1194,29 +1336,209 @@ def determine_ebin_ssd(
Parameters
----------
- energy : np.ndarray
+ energy : NDArray
Energy from the SSD event (keV).
- tof : np.ndarray
+ tof : NDArray
Time of flight of the SSD event (tenths of a nanosecond).
- path_length : np.ndarray
+ path_length : NDArray
Path length (r) (hundredths of a millimeter).
+ sensor : str
+ Sensor name: "ultra45" or "ultra90".
+ ancillary_files : dict
+ Ancillary files containing the lookup tables.
Returns
-------
- bin : np.ndarray
+ bin : NDArray
Species bin.
"""
# SSD event TOF normalization to Z axis
ctof, _ = get_ctof(tof, path_length, type="SSD")
- ebin = np.full(len(ctof), 255, dtype=np.uint8) # placeholder
+ ebins = np.full(path_length.shape, FILLVAL_UINT8, dtype=np.uint8)
+ steep_path_length = get_image_params("PathSteepThresh", sensor, ancillary_files)
+ medium_path_length = get_image_params("PathMediumThresh", sensor, ancillary_files)
+
+ steep_mask = path_length < steep_path_length
+ medium_mask = (path_length >= steep_path_length) & (
+ path_length < medium_path_length
+ )
+ flat_mask = path_length >= medium_path_length
+
+ ebins[steep_mask] = get_ebins(
+ f"l1b-{sensor[5::]}sensor-tofxesteep",
+ energy[steep_mask],
+ ctof[steep_mask],
+ ebins[steep_mask],
+ ancillary_files,
+ )
+ ebins[medium_mask] = get_ebins(
+ f"l1b-{sensor[5::]}sensor-tofxemedium",
+ energy[medium_mask],
+ ctof[medium_mask],
+ ebins[medium_mask],
+ ancillary_files,
+ )
+ ebins[flat_mask] = get_ebins(
+ f"l1b-{sensor[5::]}sensor-tofxeflat",
+ energy[flat_mask],
+ ctof[flat_mask],
+ ebins[flat_mask],
+ ancillary_files,
+ )
+
+ return ebins
+
+
+def is_back_tof_valid(
+ de_dataset: xr.Dataset,
+ xf: NDArray,
+ sensor: str,
+ ancillary_files: dict,
+ quality_flags: NDArray,
+) -> tuple[NDArray, NDArray]:
+ """
+ Determine whether back TOF is valid based on stop type.
+
+ Parameters
+ ----------
+ de_dataset : xarray.Dataset
+ Data in xarray format.
+ xf : NDArray
+ X front position in (hundredths of a millimeter).
+ Has same length as de_dataset.
+ 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 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, sensor, ancillary_files
+ )
+ diff = tofy - tofx
+
+ top_mask = de_dataset["stop_type"] == StopType.Top.value
+ bottom_mask = de_dataset["stop_type"] == StopType.Bottom.value
+
+ 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)
+ diff_bt_min = get_image_params("TOFDiffBtMin", sensor, ancillary_files)
+ diff_bt_max = get_image_params("TOFDiffBtMax", sensor, ancillary_files)
+
+ valid[top_mask] = (diff[top_mask] >= diff_tp_min) & (diff[top_mask] <= diff_tp_max)
+ valid[bottom_mask] = (diff[bottom_mask] >= diff_bt_min) & (
+ diff[bottom_mask] <= diff_bt_max
+ )
+ 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,
+ quality_flags: NDArray,
+) -> tuple[NDArray, NDArray]:
+ """
+ Determine event validity.
+
+ Parameters
+ ----------
+ etof : NDArray
+ Time for the electrons to travel back to the coincidence
+ anode (tenths of a nanosecond).
+ xc : NDArray
+ X coincidence position (hundredths of a millimeter).
+ xb : NDArray
+ 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
+ -------
+ combined_mask : NDArray
+ Boolean array indicating whether back TOF is valid.
+ quality_flags : NDArray
+ Updated quality flags.
+
+ Notes
+ -----
+ From page 36 of the IMAP-Ultra Flight Software Specification document.
+ """
+ # 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
+
+ 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
+
+ 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
- # TODO: get these lookup tables
- # if r < get_image_params("PathSteepThresh"):
- # # bin = ExTOFSpeciesSteep[energy, ctof]
- # elif r < get_image_params("PathMediumThresh"):
- # # bin = ExTOFSpeciesMedium[energy, ctof]
- # else:
- # # bin = ExTOFSpeciesFlat[energy, ctof]
+ quality_flags[~combined_mask] |= ImapDEOutliersUltraFlags.COINPH.value
- return ebin
+ return combined_mask, quality_flags
diff --git a/imap_processing/ultra/l1c/helio_pset.py b/imap_processing/ultra/l1c/helio_pset.py
index 4775d153b9..9d562aa5f0 100644
--- a/imap_processing/ultra/l1c/helio_pset.py
+++ b/imap_processing/ultra/l1c/helio_pset.py
@@ -1,27 +1,55 @@
"""Calculate 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.spice.time import sct_to_et
-from imap_processing.ultra.l1c.ultra_l1c_pset_bins import (
+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 (
+ 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 (
build_energy_bins,
- get_helio_background_rates,
- get_helio_exposure_times,
- get_helio_sensitivity,
+ 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 (
+ get_efficiencies_and_geometric_function,
+ get_energy_delta_minus_plus,
+ get_spacecraft_background_rates,
+ get_spacecraft_exposure_times,
get_spacecraft_histogram,
)
from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
+logger = logging.getLogger(__name__)
+
def calculate_helio_pset(
de_dataset: xr.Dataset,
- extendedspin_dataset: xr.Dataset,
- cullingmask_dataset: xr.Dataset,
+ goodtimes_dataset: xr.Dataset,
+ rates_dataset: xr.Dataset,
+ aux_dataset: xr.Dataset,
name: str,
ancillary_files: dict,
-) -> xr.Dataset:
+ instrument_id: int,
+ species_id: list,
+) -> xr.Dataset | None:
"""
Create dictionary with defined datatype for Pointing Set Grid Data.
@@ -29,71 +57,226 @@ 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.
+ 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 : 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(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,
+ )
+ 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(
- de_dataset["velocity_dps_helio"].values, axis=1
+ species_dataset["velocity_dps_helio"].values, axis=1
)
vhat_dps_helio = (
- de_dataset["velocity_dps_helio"].values / v_mag_helio_spacecraft[:, np.newaxis]
+ 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,
- de_dataset["energy_heliosphere"].values,
+ 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)
- # calculate background rates
- background_rates = get_helio_background_rates()
+ # Calculate the corresponding longitude (az) latitude (el)
+ # center coordinates
+ longitude, latitude = hp.pix2ang(nside, healpix, lonlat=True)
- efficiencies = ancillary_files["l1c-90sensor-efficiencies"]
- geometric_function = ancillary_files["l1c-90sensor-gf"]
+ logger.info("Calculating spacecraft exposure times with deadtime correction.")
+ exposure_time, deadtime_ratios = get_spacecraft_exposure_times(
+ rates_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
+ geometric_function, efficiencies = get_efficiencies_and_geometric_function(
+ pixels_below_scattering,
+ boundary_scale_factors,
+ theta_vals.values,
+ phi_vals.values,
+ n_pix,
+ sensor_id,
+ ancillary_files,
+ apply_bsf=UltraConstants.APPLY_BOUNDARY_SCALE_FACTORS_L1C,
+ )
- df_efficiencies = pd.read_csv(efficiencies)
- df_geometric_function = pd.read_csv(geometric_function)
- mid_time = sct_to_et(np.median(de_dataset["event_times"].data))
- sensitivity = get_helio_sensitivity(
- mid_time,
- df_efficiencies,
- df_geometric_function,
+ 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,
)
- # Calculate exposure
- constant_exposure = ancillary_files["l1c-90sensor-dps-exposure"]
- df_exposure = pd.read_csv(constant_exposure)
- exposure_pointing = get_helio_exposure_times(mid_time, df_exposure)
+ sensitivity = efficiencies * geometric_function
+
+ 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)
- # For ISTP, epoch should be the center of the time bin.
- pset_dict["epoch"] = de_dataset.epoch.data[:1].astype(np.int64)
+ # 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["background_rates"] = background_rates[np.newaxis, ...]
- pset_dict["helio_exposure_factor"] = exposure_pointing[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, ...
]
- pset_dict["sensitivity"] = sensitivity[np.newaxis, ...]
+ pset_dict["sensitivity"] = sensitivity
+ pset_dict["efficiency"] = efficiencies
+ 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
new file mode 100644
index 0000000000..341c5de8e9
--- /dev/null
+++ b/imap_processing/ultra/l1c/l1c_lookup_utils.py
@@ -0,0 +1,515 @@
+"""Contains tools for lookup tables for l1c."""
+
+import logging
+
+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,
+)
+
+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,
+) -> tuple[NDArray, NDArray, NDArray]:
+ """
+ Determine indices of theta and phi values below the FWHM scattering threshold.
+
+ For each phi and theta, calculate the FWHM using the formula:
+ FWHM = A*E^g
+ If Phi FWHM or Theta FWHM > the scattering requirements from the table above,
+ mask the instrument frame pixel.
+
+ Parameters
+ ----------
+ theta_coeffs : NDArray
+ Coefficients for theta FWHM calculation (a and g) for each pixel.
+ phi_coeffs : NDArray
+ Coefficients for phi FWHM calculation (a and g) for each pixel.
+ energy : NDArray
+ Energy corresponding to each theta and phi val in keV.
+ scattering_thresholds : dict
+ Scattering thresholds corresponding to each energy.
+
+ Returns
+ -------
+ 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] * (
+ energy ** theta_coeffs[..., 1:2]
+ ) # (npix, energy.shape[1])
+ fwhm_phi = phi_coeffs[..., 0:1] * (
+ energy ** phi_coeffs[..., 1:2]
+ ) # (npix, energy.shape[1])
+
+ thresholds = scattering_thresholds[np.newaxis, :] # (1, energy.shape[1])
+
+ # Combine conditions for both theta and phi.
+ # shape = (npix, energy.shape[1])
+ scattering_mask = np.logical_and(fwhm_theta <= thresholds, fwhm_phi <= thresholds)
+ return scattering_mask, fwhm_theta, fwhm_phi
+
+
+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,
+ reject_scattering: bool = False,
+ apply_fov_restriction: bool = False,
+) -> tuple[xr.DataArray, NDArray, NDArray, NDArray]:
+ """
+ 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 : 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
+ 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
+ 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
+ -------
+ 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)
+ # 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
+ )
+ 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):
+ 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
+ )
+ 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
+
+ # 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)
+
+ 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 (
+ 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[xr.DataArray, NDArray, NDArray, NDArray, xr.DataArray]:
+ """
+ Get indices of pixels in the nominal FOR as a function of spin phase.
+
+ This function also returns the theta / phi values in the instrument frame per spin
+ phase, right ascension / declination values in the SC frame, and boundary scale
+ factors for each pixel at each spin phase.
+
+ Parameters
+ ----------
+ ancillary_files : dict[Path]
+ Ancillary files.
+ instrument_id : int
+ Instrument ID, either 45 or 90.
+
+ Returns
+ -------
+ 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
+ A 2D array of theta values for each HEALPix pixel at each spin phase step.
+ phi_vals : NDArray
+ 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 : 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"
+ 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 = 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,
+ phi_vals,
+ ra_and_dec,
+ boundary_scale_factors,
+ )
+
+
+def get_scattering_thresholds_for_energy(
+ energy: np.ndarray, ancillary_files: dict
+) -> np.ndarray:
+ """
+ Find the scattering thresholds for each energy bin.
+
+ Parameters
+ ----------
+ energy : np.ndarray
+ Array of energy values in keV.
+ ancillary_files : dict
+ Dictionary containing ancillary files.
+
+ Returns
+ -------
+ np.ndarray
+ Array of scattering thresholds for each energy bin.
+ """
+ scattering_thresholds = get_scattering_thresholds(ancillary_files)
+ # Get thresholds for all energies
+ thresholds = []
+ for e in energy:
+ try:
+ threshold = next(
+ threshold
+ for energy_range, threshold in scattering_thresholds.items()
+ if energy_range[0] <= e < energy_range[1]
+ )
+ except StopIteration:
+ logger.warning(
+ f"Energy {e} keV is out of bounds for scattering thresholds. Using"
+ f" zero for as threshold."
+ )
+
+ 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 0ff17941a6..313b39df14 100644
--- a/imap_processing/ultra/l1c/spacecraft_pset.py
+++ b/imap_processing/ultra/l1c/spacecraft_pset.py
@@ -1,27 +1,51 @@
-"""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.ultra.l1c.ultra_l1c_pset_bins import (
+from imap_processing.cdf.utils import parse_filename_like
+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 (
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 (
+ get_efficiencies_and_geometric_function,
+ get_energy_delta_minus_plus,
get_spacecraft_background_rates,
get_spacecraft_exposure_times,
get_spacecraft_histogram,
- interpolate_sensitivity,
)
from imap_processing.ultra.utils.ultra_l1_utils import create_dataset
+logger = logging.getLogger(__name__)
+
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: list,
) -> xr.Dataset:
"""
Create dictionary with defined datatype for Pointing Set Grid Data.
@@ -30,18 +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 : List
+ Species ID.
Returns
-------
@@ -50,50 +76,200 @@ def calculate_spacecraft_pset(
"""
pset_dict: dict[str, np.ndarray] = {}
- v_mag_dps_spacecraft = np.linalg.norm(de_dataset["velocity_dps_sc"].values, axis=1)
- vhat_dps_spacecraft = (
- de_dataset["velocity_dps_sc"].values / v_mag_dps_spacecraft[:, np.newaxis]
+ 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.
+ 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=~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(
+
+ # Now check energy dependent flags.
+ energy_dependent_rejected = get_energy_and_spin_dependent_rejection_mask(
+ goodtimes_dataset,
+ species_dataset["energy_spacecraft"].values,
+ species_dataset["spin"].values,
+ )
+ 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,
+ boundary_scale_factors,
+ ) = get_spacecraft_pointing_lookup_tables(ancillary_files, instrument_id)
+
+ 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)
+
+ 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,
- de_dataset["energy_spacecraft"].values,
+ species_dataset["energy_spacecraft"].values,
intervals,
- nside=128,
+ 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 background rates
- background_rates = get_spacecraft_background_rates()
+ # Calculate the corresponding longitude (az) latitude (el)
+ # center coordinates
+ longitude, latitude = hp.pix2ang(nside, healpix, lonlat=True)
- efficiencies = ancillary_files["l1c-90sensor-efficiencies"]
- geometric_function = ancillary_files["l1c-90sensor-gf"]
+ # 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.")
- df_efficiencies = pd.read_csv(efficiencies)
- df_geometric_function = pd.read_csv(geometric_function)
- sensitivity = interpolate_sensitivity(df_efficiencies, df_geometric_function)
+ pointing_range_met = get_pointing_times_from_id(repoint_id)
- # Calculate exposure
- constant_exposure = ancillary_files["l1c-90sensor-dps-exposure"]
- df_exposure = pd.read_csv(constant_exposure)
- exposure_pointing = get_spacecraft_exposure_times(
- df_exposure, rates_dataset, params_dataset
+ # 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
+ 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 background rates
+ background_rates = get_spacecraft_background_rates(
+ rates_dataset,
+ aux_dataset,
+ sensor_id,
+ ancillary_files,
+ intervals,
+ 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.to_numpy()[np.newaxis, ...]
+ 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["sensitivity"] = sensitivity[np.newaxis, ...]
+ pset_dict["quality_flags"] = spacecraft_pset_quality_flags[np.newaxis, ...]
+
+ pset_dict["sensitivity"] = sensitivity
+ pset_dict["efficiency"] = efficiencies
+ pset_dict["geometric_function"] = geometric_function
+ 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")
diff --git a/imap_processing/ultra/l1c/ultra_l1c.py b/imap_processing/ultra/l1c/ultra_l1c.py
index 547e535bb2..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,47 +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-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[f"imap_ultra_{instrument_id}sensor-rates"],
- data_dict[f"imap_ultra_{instrument_id}sensor-params"],
+ 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",
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
new file mode 100644
index 0000000000..b1b86e4647
--- /dev/null
+++ b/imap_processing/ultra/l1c/ultra_l1c_culling.py
@@ -0,0 +1,92 @@
+"""Culling for ULTRA L1c."""
+
+import astropy_healpix.healpy as hp
+import numpy as np
+from numpy.typing import NDArray
+
+from imap_processing.quality_flags import ImapPSETUltraFlags
+from imap_processing.spice.geometry import (
+ SpiceBody,
+ SpiceFrame,
+ imap_state,
+)
+
+
+def compute_culling_mask(
+ et: NDArray,
+ keepout_radius_km: float,
+ pset_quality_flags: NDArray,
+ observer: SpiceBody = SpiceBody.EARTH,
+ nside: int = 128,
+ nested: bool = False,
+) -> tuple[NDArray, NDArray]:
+ """
+ Compute a mask for HEALPix pixels within a keep-out radius of the target body.
+
+ Parameters
+ ----------
+ et : NDArray
+ 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
+ HEALPix NSIDE resolution. Default is 128.
+ nested : bool, optional
+ Whether to use NESTED indexing.
+
+ Returns
+ -------
+ mask : tuple[NDArray, NDArray]
+ Boolean array of shape (len(et), npix).
+ unit_target_vecs : NDArray
+ Unit vectors from IMAP to the target body
+ (e.g., Earth), shape (len(et), 3).
+ """
+ # Compute number of HEALPix pixels
+ npix = hp.nside2npix(nside)
+
+ # Compute IMAP to Earth position in the pointing frame.
+ state = imap_state(et, ref_frame=SpiceFrame.IMAP_DPS, observer=observer)
+ # Flip to get vector from IMAP to Earth
+ # position.shape = (len(et), 3)
+ position = -state[:, :3]
+
+ # Distance from IMAP to target (e.g. Earth) (km):
+ # distance.shape = (len(et),)
+ distance = np.linalg.norm(position, axis=1) # shape (len(et),)
+
+ # Calculate the keepout angle (radians).
+ # keepout_angle.shape = (len(et),)
+ keepout_angle = np.arcsin(keepout_radius_km / distance) # radians
+
+ # Calculate the direction from IMAP to Earth. (shape: [N, 3])
+ # unit_target_vecs.shape = (len(et), 3)
+ unit_target_vecs = position / distance[:, np.newaxis]
+
+ # Get pixel unit vectors pointing from the center of the
+ # HEALPix sphere to the center of each pixel on the sky.
+ pixel_vecs = np.column_stack(
+ hp.pix2vec(nside, np.arange(npix), nest=nested)
+ ) # shape: (npix, 3)
+
+ # Returns cos(theta) where theta is the separation angle between:
+ # (1) vector from IMAP to Earth
+ # (2) vector from IMAP to HEALPix pixel center
+ # If theta is within the keepout angle, then the pixel is culled.
+ cos_sep = np.dot(unit_target_vecs, pixel_vecs.T) # shape (N, npix)
+ cos_sep = np.clip(cos_sep, -1.0, 1.0)
+ # Get theta here.
+ sep_angle = np.arccos(cos_sep)
+
+ # 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 5fa5ab68e8..cc33e02596 100644
--- a/imap_processing/ultra/l1c/ultra_l1c_pset_bins.py
+++ b/imap_processing/ultra/l1c/ultra_l1c_pset_bins.py
@@ -1,61 +1,55 @@
"""Module to create pointing sets."""
+import logging
+
import astropy_healpix.healpy as hp
import numpy as np
-import pandas
-import pandas as pd
import xarray as xr
from numpy.typing import NDArray
-from scipy.interpolate import interp1d
+from scipy import interpolate
from imap_processing.spice.geometry import (
- SpiceFrame,
cartesian_to_spherical,
- imap_state,
)
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,
+)
+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.
- """
- # Calculate energy step
- energy_step = (1 + UltraConstants.ALPHA / 2) / (1 - UltraConstants.ALPHA / 2)
-
- # Create energy bins.
- energy_bin_edges = UltraConstants.ENERGY_START * energy_step ** np.arange(
- UltraConstants.N_BINS + 1
- )
- # Add a zero to the left side for outliers and round to nearest 3 decimal places.
- energy_bin_edges = np.around(np.insert(energy_bin_edges, 0, 0), 3)
- 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
@@ -71,9 +65,9 @@ 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):
+ 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)
bins_energy_delta_minus.append(bin_geom_mean - bin_edges[0])
return abs(np.array(bins_energy_delta_minus)), abs(np.array(bins_energy_delta_plus))
@@ -85,9 +79,9 @@ 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 3D histogram of the particle data using HEALPix binning.
+ Compute a 2D histogram of the particle data using HEALPix binning.
Parameters
----------
@@ -106,11 +100,7 @@ def get_spacecraft_histogram(
Returns
-------
hist : np.ndarray
- A 3D histogram array with shape (n_pix, n_energy_bins).
- latitude : np.ndarray
- Array of latitude values.
- longitude : np.ndarray
- Array of longitude values.
+ A 2D histogram array with shape (n_pix, n_energy_bins).
n_pix : int
Number of healpix pixels.
@@ -132,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)
@@ -149,69 +135,47 @@ 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_background_rates(
- nside: int = 128,
-) -> NDArray:
+def get_spacecraft_count_rate_uncertainty(hist: NDArray, exposure: NDArray) -> NDArray:
"""
- Calculate background rates.
+ Calculate the count rate uncertainty for HEALPix-binned data.
Parameters
----------
- nside : int, optional
- The nside parameter of the Healpix tessellation (default is 128).
+ hist : NDArray
+ A 2D histogram array with shape (n_pix, n_energy_bins).
+ exposure : NDArray
+ A 2D array of exposure times with shape (n_pix, n_energy_bins).
Returns
-------
- background_rates : np.ndarray
- Array of background rates.
+ count_rate_uncertainty : NDArray
+ Rate uncertainty with shape (n_pix, n_energy_bins) (counts/sec).
Notes
-----
- This is a placeholder.
- TODO: background rates to be provided by IT.
+ These calculations were based on Eqn 15 from the IMAP-Ultra Algorithm Document.
"""
- npix = hp.nside2npix(nside)
- _, energy_midpoints, _ = build_energy_bins()
- background = np.zeros((len(energy_midpoints), npix))
- return background
+ count_uncertainty = np.sqrt(hist)
+ rate_uncertainty = np.zeros_like(hist)
+ valid = exposure > 0
+ rate_uncertainty[valid] = count_uncertainty[valid] / exposure[valid]
-def get_helio_background_rates(
- nside: int = 128,
-) -> NDArray:
- """
- Calculate background rates.
+ return rate_uncertainty
- Parameters
- ----------
- nside : int, optional
- The nside parameter of the Healpix tessellation (default is 128).
- Returns
- -------
- background_rates : np.ndarray
- Array of background rates.
-
- Notes
- -----
- This is a placeholder.
- TODO: background rates to be provided by IT.
+def get_deadtime_ratios(sectored_rates_ds: xr.Dataset) -> xr.DataArray:
"""
- npix = hp.nside2npix(nside)
- _, energy_midpoints, _ = build_energy_bins()
- background = np.zeros((len(energy_midpoints), npix))
- return background
+ Compute the dead time ratio at each sector.
-
-def get_deadtime_correction_factors(sectored_rates_ds: xr.Dataset) -> xr.DataArray:
- """
- Compute the dead time correction factor at each sector.
-
- Further description is available in section 3.4.3 of the IMAP-Ultra Algorithm
- Document.
+ A reduction in exposure time (duty cycle) is caused by the flight hardware listening
+ for coincidence events that never occur, due to singles starts predominantly from UV
+ radiation. The static exposure time for a given Pointing should be reduced by this
+ spatially dependent exposure time reduction factor (the dead time). Further
+ description is available in section 3.4.3 of the IMAP-Ultra Algorithm Document.
Parameters
----------
@@ -223,410 +187,575 @@ def get_deadtime_correction_factors(sectored_rates_ds: xr.Dataset) -> xr.DataArr
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)
- ]
-
- sector_mode_mask = np.logical_or.reduce(conditions)
- return rates_ds.isel(epoch=sector_mode_mask)
-
-
-def get_spacecraft_exposure_times(
- constant_exposure: pandas.DataFrame,
- rates_dataset: xr.Dataset,
- params_dataset: xr.Dataset,
-) -> NDArray:
+ 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 | None,
+ aux_dataset: xr.Dataset,
+ spin_steps: int,
+ sensor_id: int | None = None,
+ ancillary_files: dict | None = None,
+) -> xr.DataArray:
"""
- Compute exposure times for HEALPix pixels.
+ Calculate nominal deadtime ratios at every spin phase step (1ms res).
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.
-
- Returns
- -------
- exposure_pointing : np.ndarray
- Total exposure times of pixels in a
- Healpix tessellation of the sky
- in the pointing (dps) frame.
- """
- # TODO: uncomment these lines when the deadtime correction is implemented
- # sectored_rates = get_sectored_rates(rates_dataset, params_dataset)
- # get_deadtime_correction_factors(sectored_rates)
- # TODO: calculate the deadtime correction function
- # TODO: Apply the deadtime correction to the exposure times
- # TODO: use the universal spin table and
- # universal pointing table here to determine actual number of spins
- exposure_pointing = (
- constant_exposure["Exposure Time"] * 5760
- ) # 5760 spins per pointing (for now)
-
- return exposure_pointing
-
-
-def get_helio_exposure_times(
- time: np.ndarray,
- df_exposure: pd.DataFrame,
- nside: int = 128,
- nested: bool = False,
-) -> NDArray:
- """
- Compute a 2D (Healpix index, energy) array of exposure in the helio frame.
-
- Parameters
- ----------
- time : np.ndarray
- Median time of pointing in et.
- df_exposure : pd.DataFrame
- Spacecraft exposure in healpix coordinates.
- 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).
+ 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
-------
- helio_exposure : np.ndarray
- A 2D array of shape (npix, n_energy_bins).
-
- Notes
- -----
- These calculations are performed once per pointing.
+ xarray.DataArray
+ Nominal deadtime ratios at every spin phase step.
"""
- # Get energy midpoints.
- _, energy_midpoints, _ = build_energy_bins()
- # Extract (RA/Dec) and exposure from the spacecraft frame.
- ra = df_exposure["Right Ascension (deg)"].values
- dec = df_exposure["Declination (deg)"].values
- exposure_flat = df_exposure["Exposure Time"].values
-
- # 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.
- unit_dirs = hp.ang2vec(ra, dec, lonlat=True).T # Shape (N, 3)
-
- # Initialize output array.
- # Each row corresponds to a HEALPix pixel, and each column to an energy bin.
- npix = hp.nside2npix(nside)
- helio_exposure = np.zeros((len(energy_midpoints), npix))
-
- # Loop through energy bins and compute transformed exposure.
- for i, energy_midpoint in enumerate(energy_midpoints):
- # 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_midpoint * UltraConstants.KEV_J / UltraConstants.MASS_H)
- / 1e3
+ 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."
)
-
- # 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
+ 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
)
-
- # 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 values into HEALPix pixels for this energy bin.
- helio_exposure[i, :] = np.bincount(
- hpix_idx, weights=exposure_flat, minlength=npix
+ else:
+ num_spin_sectors = 15
+ sector_indices: np.ndarray = (
+ np.arange(len(sectored_rates["epoch"])) % num_spin_sectors
)
-
- return helio_exposure
+ # 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": (("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)):
+ 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 the supplied resolution and query the pchip
+ # interpolator to get the deadtime ratios.
+ 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 get_spacecraft_sensitivity(
- efficiencies: pandas.DataFrame,
- geometric_function: pandas.DataFrame,
-) -> tuple[pandas.DataFrame, NDArray, NDArray, 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:
"""
- Compute sensitivity as efficiency * geometric factor.
+ Adjust the exposure time at each pixel to account for dead time.
Parameters
----------
- efficiencies : pandas.DataFrame
- Efficiencies at different energy levels.
- geometric_function : pandas.DataFrame
- Geometric function.
+ 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
-------
- pointing_sensitivity : pandas.DataFrame
- Sensitivity with dimensions (HEALPIX pixel_number, energy).
- energy_vals : NDArray
- Energy values of dataframe.
- right_ascension : NDArray
- Right ascension (longitude/azimuth) values of dataframe (0 - 360 degrees).
- declination : NDArray
- Declination (latitude/elevation) values of dataframe (-90 to 90 degrees).
+ exposure_pointing: xarray.DataArray
+ Adjusted exposure times accounting for dead time.
+ Shape: ``(energy, pixel)``.
"""
- # Exclude "Right Ascension (deg)" and "Declination (deg)" from the multiplication
- energy_columns = [
- col
- for col in efficiencies.columns
- if col not in ["Right Ascension (deg)", "Declination (deg)"]
- ]
- sensitivity = efficiencies[energy_columns].mul(
- geometric_function["Response (cm2-sr)"].values, axis=0
- )
-
- right_ascension = efficiencies["Right Ascension (deg)"]
- declination = efficiencies["Declination (deg)"]
-
- energy_vals = np.array([float(col.replace("keV", "")) for col in energy_columns])
-
- return sensitivity, energy_vals, right_ascension, declination
+ # nominal spin phase 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 (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 grid_sensitivity(
- efficiencies: pandas.DataFrame,
- geometric_function: pandas.DataFrame,
- energy: float,
-) -> NDArray:
+def get_spacecraft_exposure_times(
+ rates_dataset: xr.Dataset,
+ 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]:
"""
- Grid the sensitivity.
+ Compute exposure times for HEALPix pixels.
Parameters
----------
- efficiencies : pandas.DataFrame
- Efficiencies at different energy levels.
- geometric_function : pandas.DataFrame
- Geometric function.
- energy : float
- Energy to which we are interpolating.
+ rates_dataset : xarray.Dataset
+ Dataset containing image rates data.
+ 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
-------
- interpolated_sensitivity : np.ndarray
- Sensitivity with dimensions (HEALPIX pixel_number, 1).
+ exposure_pointing : np.ndarray
+ 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).
"""
- sensitivity, energy_vals, right_ascension, declination = get_spacecraft_sensitivity(
- efficiencies, geometric_function
+ 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
)
-
- # Create interpolator over energy dimension for each pixel (axis=1)
- interp_func = interp1d(
- energy_vals,
- sensitivity.values,
- axis=1,
- bounds_error=False,
- fill_value=np.nan,
+ # 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
)
- # Interpolate to energy
- interpolated = interp_func(energy)
- interpolated = np.where(np.isnan(interpolated), FILLVAL_FLOAT32, interpolated)
-
- return interpolated
-
-
-def interpolate_sensitivity(
- efficiencies: pd.DataFrame,
- geometric_function: pd.DataFrame,
- nside: int = 128,
-) -> NDArray:
+ 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(
+ 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]:
"""
- Interpolate the sensitivity and bin it in HEALPix space.
+ Compute the geometric factor and efficiency for each pixel and energy bin.
+
+ The results are averaged over all spin phases.
Parameters
----------
- efficiencies : pandas.DataFrame
- Efficiencies at different energy levels.
- geometric_function : pandas.DataFrame
- Geometric function.
- nside : int, optional
- Healpix nside resolution (default is 128).
+ 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
+ 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
+ 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
-------
- interpolated_sensitivity : np.ndarray
- Array of shape (n_energy_bins, n_healpix_pixels).
+ 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).
"""
- _, _, energy_bin_geometric_means = build_energy_bins()
- npix = hp.nside2npix(nside)
-
- interpolated_sensitivity = np.full(
- (len(energy_bin_geometric_means), npix), FILLVAL_FLOAT32
+ sensor_name = f"ultra{sensor_id}"
+ # Load callable efficiency interpolator function
+ eff_interpolator, theta_min_max, phi_min_max, e_min_max = (
+ get_efficiency_interpolator(ancillary_files, sensor_name)
)
-
- for i, energy in enumerate(energy_bin_geometric_means):
- pixel_sensitivity = grid_sensitivity(
- efficiencies, geometric_function, energy
- ).flatten()
- interpolated_sensitivity[i, :] = pixel_sensitivity
-
- return interpolated_sensitivity
+ # load geometric factor lookup table
+ geometric_lookup_table = load_geometric_factor_tables(
+ ancillary_files, "l1b-sensor-gf-blades"
+ )
+ # 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
+ spin_steps = valid_spun_pixels.sizes["spin_phase_step"]
+ for i in range(spin_steps):
+ # Loop through energy bins
+ # 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):
+ # 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(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 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.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_sensitivity(
- time: np.ndarray,
- efficiencies: pandas.DataFrame,
- geometric_function: pandas.DataFrame,
+def get_spacecraft_background_rates(
+ rates_dataset: xr.Dataset,
+ aux_dataset: xr.Dataset,
+ sensor_id: int,
+ ancillary_files: dict,
+ energy_bin_edges: list[tuple[float, float]],
+ goodtimes_spin_number: NDArray,
nside: int = 128,
- nested: bool = False,
) -> NDArray:
"""
- Compute a 2D (Healpix index, energy) array of sensitivity in the helio frame.
+ Calculate background rates based on the provided parameters.
Parameters
----------
- time : np.ndarray
- Median time of pointing in et.
- efficiencies : pandas.DataFrame
- Efficiencies at different energy levels.
- geometric_function : pandas.DataFrame
- Geometric function.
+ rates_dataset : xr.Dataset
+ Rates dataset.
+ 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.
+ goodtimes_spin_number : NDArray
+ Goodtime spins.
+ 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).
- nested : bool, optional
- Whether the Healpix tessellation is nested (default is False).
Returns
-------
- helio_sensitivity : np.ndarray
- A 2D array of shape (npix, n_energy_bins).
+ background_rates : NDArray of shape (n_energy_bins, n_HEALPix pixels)
+ Calculated background rates.
Notes
-----
- These calculations are performed once per pointing.
+ See Eqn. 3, 8, and 20 in the Algorithm Document for the equation.
"""
- # Get energy midpoints.
- _, energy_midpoints, _ = build_energy_bins()
-
- # Get sensitivity on the spacecraft grid
- _, _, ra, dec = get_spacecraft_sensitivity(efficiencies, geometric_function)
-
- # 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 sensitivity.
- unit_dirs = hp.ang2vec(ra, dec, lonlat=True).T # Shape (N, 3)
-
- # Initialize output array.
- # Each row corresponds to a HEALPix pixel, and each column to an energy bin.
- npix = hp.nside2npix(nside)
- helio_sensitivity = np.zeros((len(energy_midpoints), npix))
-
- # Loop through energy bins and compute transformed sensitivity.
- for i, energy in enumerate(energy_midpoints):
- # 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 * UltraConstants.KEV_J / UltraConstants.MASS_H) / 1e3
- )
+ pulses = get_pulses_per_spin(aux_dataset, rates_dataset)
+ # Pulses for the pointing.
+ 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
- # 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
- )
+ # Get dmin for PH (mm).
+ dmin_ctof = UltraConstants.DMIN_PH_CTOF
- # 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]
+ # Compute number of HEALPix pixels that cover the sphere
+ n_pix = hp.nside2npix(nside)
- # Convert azimuth/elevation directions to HEALPix pixel indices.
- hpix_idx = hp.ang2pix(nside, az, el, nest=nested, lonlat=True)
- gridded_sensitivity = grid_sensitivity(efficiencies, geometric_function, energy)
+ # Initialize background rate array: (n_energy_bins, n_HEALPix pixels)
+ background_rates = np.zeros((len(energy_bin_edges), n_pix))
- # Accumulate sensitivity values into HEALPix pixels for this energy bin.
- helio_sensitivity[i, :] = np.bincount(
- hpix_idx, weights=gridded_sensitivity, minlength=npix
- )
+ # Only select pulses from goodtimes.
+ 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])
- return helio_sensitivity
+ for i, (e_min, e_max) in enumerate(energy_bin_edges):
+ # Calculate ctof for the energy bin boundaries by combining Eqn. 3 and 8.
+ # Compute speed for min and max energy using E = 1/2mv^2 -> v = sqrt(2E/m)
+ vmin = np.sqrt(2 * e_min * UltraConstants.KEV_J / UltraConstants.MASS_H) # m/s
+ vmax = np.sqrt(2 * e_max * UltraConstants.KEV_J / UltraConstants.MASS_H) # m/s
+ # Compute cTOF = dmin / v
+ # Multiply times 1e-3 to convert to m.
+ ctof_min = dmin_ctof * 1e-3 / vmax * 1e-9 # Convert to ns
+ ctof_max = dmin_ctof * 1e-3 / vmin * 1e-9 # Convert to ns
+
+ background_rates[i, :] = (
+ np.abs(ctof_max - ctof_min)
+ * (etof_max - etof_min)
+ * mean_start_pulses
+ * mean_stop_pulses
+ * mean_coin_pulses
+ ) / 30.0
+
+ return background_rates
diff --git a/imap_processing/ultra/l2/ultra_l2.py b/imap_processing/ultra/l2/ultra_l2.py
index 6f53d33a69..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,10 +19,15 @@
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__)
-logger.info("Importing ultra_l2 module")
# Default properties for the Ultra L2 map
DEFAULT_ULTRA_L2_MAP_STRUCTURE: ena_maps.RectangularSkyMap | ena_maps.HealpixSkyMap = (
@@ -48,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 = [
@@ -55,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",
]
@@ -90,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,
@@ -128,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,
@@ -136,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
----------
@@ -158,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.
@@ -175,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.
@@ -184,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",
]
)
@@ -236,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 "
@@ -249,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),
)
@@ -262,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
@@ -274,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
@@ -293,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(
@@ -316,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
@@ -348,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
@@ -358,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)
@@ -370,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,
@@ -385,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.
@@ -402,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."
@@ -410,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
@@ -422,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,),
[
@@ -443,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")
@@ -468,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),
}
@@ -477,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:
@@ -498,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),
@@ -542,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=[
@@ -559,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(
[
@@ -571,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
@@ -589,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:
@@ -607,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 da22f93dd5..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,7 +46,9 @@ 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"],
}
default_dimension = "pixel_index"
# L1b de data product
@@ -94,16 +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", "spin_number", "energy_bin_geometric_mean", "pixel_index"]:
+ 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",
+ ]:
+ # 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"],
@@ -127,23 +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", "exposure_factor"}:
+ 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",
- "sensitivity",
}:
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 {
+ "geometric_function",
+ "scatter_theta",
+ "scatter_phi",
+ "sensitivity",
+ "efficiency",
+ }:
+ 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"}:
+ 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,
@@ -172,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 6cc989bb54..b1b8353c47 100644
--- a/imap_processing/utils.py
+++ b/imap_processing/utils.py
@@ -2,25 +2,36 @@
import collections
import logging
+from collections.abc import Generator
+from datetime import datetime, timedelta
from pathlib import Path
-from typing import Optional, Union
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.
@@ -28,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
@@ -44,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
@@ -141,7 +152,7 @@ def _get_minimum_numpy_datatype( # noqa: PLR0912 - Too many branches
name: str,
definition: definitions.XtcePacketDefinition,
use_derived_value: bool = True,
-) -> Optional[str]:
+) -> str | None:
"""
Get the minimum datatype for a given variable.
@@ -159,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
@@ -209,8 +220,8 @@ def _get_minimum_numpy_datatype( # noqa: PLR0912 - Too many branches
def packet_file_to_datasets(
- packet_file: Union[str, Path],
- xtce_packet_definition: Union[str, Path],
+ packet_file: str | Path,
+ xtce_packet_definition: str | Path,
use_derived_value: bool = False,
) -> dict[int, xr.Dataset]:
"""
@@ -255,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(
@@ -326,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(
@@ -343,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.
@@ -359,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 40f98925ec..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"},
@@ -179,13 +192,14 @@ lxml = ["lxml"]
[[package]]
name = "cdflib"
-version = "1.3.4"
+version = "1.3.6"
description = "A python CDF reader toolkit"
optional = false
python-versions = ">=3.9"
+groups = ["main"]
files = [
- {file = "cdflib-1.3.4-py3-none-any.whl", hash = "sha256:de59d7e878762ca2f4d537d6e4ff50abbfdc1e1ea38cdf3d23a9a61a7678a903"},
- {file = "cdflib-1.3.4.tar.gz", hash = "sha256:f32f679624982cbfd7677ffb8741c087071c03df5650e3148259a387b67e3110"},
+ {file = "cdflib-1.3.6-py3-none-any.whl", hash = "sha256:ed343840b6cd0b5f32281405823c9b7b01360bc0480b5939e9abec1e9c0c2e60"},
+ {file = "cdflib-1.3.6.tar.gz", hash = "sha256:61084895f68c7a127305bcec3e4178e123db97fca6aff3824bd08b014e4ff1f2"},
]
[package.dependencies]
@@ -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"},
@@ -793,8 +863,11 @@ files = [
{file = "lxml-5.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7ce1a171ec325192c6a636b64c94418e71a1964f56d002cc28122fceff0b6121"},
{file = "lxml-5.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:795f61bcaf8770e1b37eec24edf9771b307df3af74d1d6f27d812e15a9ff3872"},
{file = "lxml-5.4.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29f451a4b614a7b5b6c2e043d7b64a15bd8304d7e767055e8ab68387a8cacf4e"},
+ {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:891f7f991a68d20c75cb13c5c9142b2a3f9eb161f1f12a9489c82172d1f133c0"},
{file = "lxml-5.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4aa412a82e460571fad592d0f93ce9935a20090029ba08eca05c614f99b0cc92"},
+ {file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:ac7ba71f9561cd7d7b55e1ea5511543c0282e2b6450f122672a2694621d63b7e"},
{file = "lxml-5.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:c5d32f5284012deaccd37da1e2cd42f081feaa76981f0eaa474351b68df813c5"},
+ {file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:ce31158630a6ac85bddd6b830cffd46085ff90498b397bd0a259f59d27a12188"},
{file = "lxml-5.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:31e63621e073e04697c1b2d23fcb89991790eef370ec37ce4d5d469f40924ed6"},
{file = "lxml-5.4.0-cp37-cp37m-win32.whl", hash = "sha256:be2ba4c3c5b7900246a8f866580700ef0d538f2ca32535e991027bdaba944063"},
{file = "lxml-5.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:09846782b1ef650b321484ad429217f5154da4d6e786636c38e434fa32e94e49"},
@@ -853,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"},
@@ -923,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"},
@@ -943,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"},
@@ -990,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"},
@@ -1001,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"},
@@ -1031,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"},
]
@@ -1048,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"},
@@ -1059,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"},
@@ -1123,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"},
@@ -1134,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"]
@@ -1144,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"},
@@ -1158,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"},
@@ -1169,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"},
@@ -1255,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"},
@@ -1266,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"},
@@ -1282,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"},
@@ -1297,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"},
@@ -1315,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"},
@@ -1342,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"},
@@ -1367,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"},
@@ -1383,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"},
@@ -1405,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"},
@@ -1423,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"},
@@ -1443,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"},
@@ -1457,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"},
@@ -1468,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"},
@@ -1530,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"},
@@ -1546,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"},
@@ -1561,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"},
@@ -1686,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]]
@@ -1716,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"},
]
@@ -1735,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"},
@@ -1790,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"
@@ -1798,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"},
@@ -1809,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"},
@@ -1820,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"},
@@ -1827,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"
@@ -1845,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"},
@@ -1880,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"},
@@ -1892,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"
@@ -1900,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"},
@@ -1916,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"},
@@ -1932,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"},
@@ -1948,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"},
@@ -1963,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"},
@@ -1977,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"},
@@ -1997,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"},
@@ -2013,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"},
@@ -2029,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"},
@@ -2051,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"},
@@ -2065,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"},
@@ -2106,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"},
@@ -2117,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"},
@@ -2128,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)"]
@@ -2145,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"},
@@ -2157,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"
@@ -2165,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"},
@@ -2179,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"]
@@ -2192,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 = "4a9eea6df9cb83e67a574ccbe9302ed41d8090a6b2dfecd20afea659613a15bb"
+lock-version = "2.1"
+python-versions = ">=3.10,<3.13"
+content-hash = "3d52d625a144e78ed95e527798289d6b0d5780bd25e80a94bec7197cc9863f35"
diff --git a/pyproject.toml b/pyproject.toml
index bd68144494..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.1"
-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,9 +93,8 @@ markers = [
"use_test_metakernel: Mark test to use a test metakernel"
]
-
[tool.ruff]
-target-version = "py39"
+target-version = "py310"
lint.select = ["B", "D", "E", "F", "I", "N", "S", "W", "PL", "PT", "UP", "RUF"]
lint.ignore = [
"D104", # Missing docstring in public package
@@ -99,22 +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
]
[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"
@@ -136,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 ',
]
@@ -154,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/metadata_generation/metadata_generator.py b/tools/metadata_generation/metadata_generator.py
index 0915037775..1486f33b5c 100644
--- a/tools/metadata_generation/metadata_generator.py
+++ b/tools/metadata_generation/metadata_generator.py
@@ -1,7 +1,6 @@
"""SWAPI metadata generator."""
from pathlib import Path
-from typing import Optional, Union
import pandas as pd
import yaml
@@ -29,7 +28,7 @@ def get_global_attributes(sheet: pd.DataFrame) -> pd.DataFrame:
def get_dataset_attributes(
- sheet: pd.DataFrame, global_attrs: Optional[dict] = None
+ sheet: pd.DataFrame, global_attrs: dict | None = None
) -> dict:
"""
Get the dataset attributes from a metadata spreadsheet.
@@ -67,7 +66,7 @@ def get_dataset_attributes(
# Load all sheets
-def process_file(excel_path: Union[str, Path], output_folder: Path) -> None:
+def process_file(excel_path: str | Path, output_folder: Path) -> None:
"""
Will process the metadata file and output the metadata to a JSON file.
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]
diff --git a/tools/spice/spice_utils.py b/tools/spice/spice_utils.py
index d584c852f9..839b682066 100644
--- a/tools/spice/spice_utils.py
+++ b/tools/spice/spice_utils.py
@@ -2,7 +2,6 @@
import logging
import os
-from typing import Optional
import spiceypy
@@ -10,7 +9,7 @@
def list_files_with_extensions(
- directory: str, extensions: Optional[list[str]] = None
+ directory: str, extensions: list[str] | None = None
) -> list[str]:
"""
List all files in a given directory that have the specified extensions.
@@ -44,7 +43,7 @@ def list_files_with_extensions(
return matching_files
-def list_loaded_kernels(extensions: Optional[list[str]] = None) -> list:
+def list_loaded_kernels(extensions: list[str] | None = None) -> list:
"""
List furnished spice kernels, optionally filtered by specific extensions.