Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ultra Extended L1b Front Coordinates #730

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions imap_processing/tests/ultra/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
import sys
from pathlib import Path

import numpy as np
import pytest

from imap_processing import decom
from imap_processing.ultra.l0.decom_ultra import process_ultra_apids
from imap_processing.ultra.l0.ultra_utils import (
ULTRA_AUX,
ULTRA_EVENTS,
)
from imap_processing.ultra.l1a import ultra_l1a
from imap_processing.utils import group_by_apid


Expand Down Expand Up @@ -161,3 +167,44 @@ def decom_test_data(request, xtce_path):

data_packet_list = process_ultra_apids(grouped_data[apid], apid)
return data_packet_list, packets


@pytest.fixture()
def events_fsw_comparison_theta_0():
"""FSW test data."""
filename = (
"FM45_40P_Phi28p5_BeamCal_LinearScan_phi28.50_theta-0.00"
"_Ultra_Image_Raw_Event_20240207T102746_withFSWcalcs.csv"
)
return (
Path(sys.modules[__name__.split(".")[0]].__file__).parent
/ "tests"
/ "ultra"
/ "test_data"
/ "l0"
/ filename
)


@pytest.fixture()
def de_dataset(ccsds_path_theta_0, xtce_path):
"""L1A test data"""
packets = decom.decom_packets(ccsds_path_theta_0, xtce_path)
grouped_data = group_by_apid(packets)
decom_ultra_events = process_ultra_apids(
grouped_data[ULTRA_EVENTS.apid[0]], ULTRA_EVENTS.apid[0]
)
decom_ultra_aux = process_ultra_apids(
grouped_data[ULTRA_AUX.apid[0]], ULTRA_AUX.apid[0]
)
dataset = ultra_l1a.create_dataset(
{
ULTRA_EVENTS.apid[0]: decom_ultra_events,
ULTRA_AUX.apid[0]: decom_ultra_aux,
}
)
# Remove start_type with fill values
l1a_de_dataset = dataset.where(
dataset["START_TYPE"] != np.iinfo(np.int64).min, drop=True
)
return l1a_de_dataset
42 changes: 42 additions & 0 deletions imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Tests Extended Raw Events for ULTRA L1b."""

import pandas as pd
import pytest

from imap_processing.ultra.l1b.ultra_l1b_extended import (
get_front_x_position,
get_front_y_position,
)


def test_get_front_x_position(
de_dataset,
events_fsw_comparison_theta_0,
):
"""Tests get_front_x_position function."""

df = pd.read_csv(events_fsw_comparison_theta_0)
df_filt = df[df["StartType"] != -1]

xf = get_front_x_position(
de_dataset["START_TYPE"].data,
de_dataset["START_POS_TDC"].data,
)

assert xf == pytest.approx(df_filt["Xf"].astype("float"), 1e-5)


def test_get_front_y_position(
de_dataset,
events_fsw_comparison_theta_0,
):
"""Tests get_front_y_position function."""

df = pd.read_csv(events_fsw_comparison_theta_0)
df_filt = df[df["StartType"] != -1]

d, yf = get_front_y_position(
de_dataset["START_TYPE"].data, df_filt.Yb.values.astype("float")
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: there is no test data for the value of d.


assert yf == pytest.approx(df_filt["Yf"].astype("float"), abs=1e-5)
9 changes: 9 additions & 0 deletions imap_processing/ultra/l1b/l1b_extended_config.py
laspsandoval marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""Extended Raw Events for ULTRA L1b Constants."""

# Constants in IMAP-Ultra Flight Software Specification document.
D_SLIT_FOIL = 3.39 # shortest distance from slit to foil (mm)
SLIT_Z = 44.89 # position of slit on Z axis (mm)
YF_ESTIMATE_LEFT = 40.0 # front position of particle for left shutter (mm)
YF_ESTIMATE_RIGHT = -40 # front position of particle for right shutter (mm)
N_ELEMENTS = 256 # number of elements in lookup table
TRIG_CONSTANT = 81.92 # trigonometric constant (mm)
2 changes: 1 addition & 1 deletion imap_processing/ultra/l1b/lookup_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def get_y_adjust(dy_lut: np.ndarray) -> np.ndarray:
yadj : np.ndarray
Y adjustment (mm).
"""
return _YADJUST_DF["dYAdj"].values[dy_lut]
return _YADJUST_DF["dYAdj"].iloc[dy_lut].values


def get_norm(dn: np.ndarray, key: str, file_label: str) -> np.ndarray:
Expand Down
115 changes: 115 additions & 0 deletions imap_processing/ultra/l1b/ultra_l1b_extended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"""Calculates Extended Raw Events for ULTRA L1b."""

import numpy as np

from imap_processing.ultra.l1b.l1b_extended_config import (
D_SLIT_FOIL,
N_ELEMENTS,
SLIT_Z,
TRIG_CONSTANT,
YF_ESTIMATE_LEFT,
YF_ESTIMATE_RIGHT,
)
from imap_processing.ultra.l1b.lookup_utils import (
get_image_params,
get_y_adjust,
)

# TODO: make lookup tables into config files.


def get_front_x_position(
start_type: np.array, start_position_tdc: np.array
) -> np.array:
"""
Calculate the front xf position.

Converts Start Position Time to Digital Converter (TDC)
values into units of hundredths of a millimeter using a scale factor and offsets.
Further description is available on pages 30 of
IMAP-Ultra Flight Software Specification document (7523-9009_Rev_-.pdf).

Parameters
----------
start_type : np.array
Start Type: 1=Left, 2=Right.
start_position_tdc : np.array
Start Position Time to Digital Converter (TDC).

Returns
-------
xf : np.array
X front position (hundredths of a millimeter).
"""
# Left and right start types.
indices = np.where((start_type == 1) | (start_type == 2))
laspsandoval marked this conversation as resolved.
Show resolved Hide resolved

xftsc = get_image_params("XFTSC")
xft_lt_off = get_image_params("XFTLTOFF")
xft_rt_off = get_image_params("XFTRTOFF")
xft_off = np.where(start_type[indices] == 1, xft_lt_off, xft_rt_off)

# Calculate xf and convert to hundredths of a millimeter
xf = (xftsc * -start_position_tdc[indices] + xft_off) * 100

return xf


def get_front_y_position(
start_type: np.array, yb: np.array
) -> tuple[np.array, np.array]:
"""
Compute the adjustments for the front y position and distance front to back.

This function utilizes lookup tables and trigonometry based on
the angle of the foil. Further description is available in the
IMAP-Ultra Flight Software Specification document pg 30.

Parameters
----------
start_type : np.array
Start Type: 1=Left, 2=Right.
yb : np.array
Y back position in hundredths of a millimeter.

Returns
-------
d : np.array
Distance front to back in hundredths of a millimeter.
yf : np.array
Front y position in hundredths of a millimeter.
"""
# Determine start types
index_left = np.where(start_type == 1)
index_right = np.where(start_type == 2)
laspsandoval marked this conversation as resolved.
Show resolved Hide resolved

yf = np.zeros(len(start_type))
d = np.zeros(len(start_type))

# Compute adjustments for left start type
dy_lut_left = np.floor(
(YF_ESTIMATE_LEFT - yb[index_left] / 100) * N_ELEMENTS / TRIG_CONSTANT + 0.5
)
# y adjustment in mm
y_adjust_left = get_y_adjust(dy_lut_left) / 100
# hundredths of a millimeter
yf[index_left] = (YF_ESTIMATE_LEFT - y_adjust_left) * 100
# distance adjustment in mm
distance_adjust_left = np.sqrt(2) * D_SLIT_FOIL - y_adjust_left
# hundredths of a millimeter
d[index_left] = (SLIT_Z - distance_adjust_left) * 100

# Compute adjustments for right start type
dy_lut_right = np.floor(
(yb[index_right] / 100 - YF_ESTIMATE_RIGHT) * N_ELEMENTS / TRIG_CONSTANT + 0.5
)
# y adjustment in mm
y_adjust_right = get_y_adjust(dy_lut_right) / 100
# hundredths of a millimeter
yf[index_right] = (YF_ESTIMATE_RIGHT + y_adjust_right) * 100
# distance adjustment in mm
distance_adjust_right = np.sqrt(2) * D_SLIT_FOIL - y_adjust_right
# hundredths of a millimeter
d[index_right] = (SLIT_Z - distance_adjust_right) * 100

return d, yf
Loading