Skip to content

Commit

Permalink
Change allowed_rolldev to use chandra_models
Browse files Browse the repository at this point in the history
  • Loading branch information
taldcroft committed Feb 28, 2023
1 parent f223755 commit d963e45
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 32 deletions.
42 changes: 27 additions & 15 deletions ska_sun/sun.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Utility for calculating sun position, pitch angle and values related to roll.
"""
from math import acos, asin, atan2, cos, degrees, pi, radians, sin
from pathlib import Path

import numpy as np
import Ska.quatutil
Expand All @@ -12,14 +11,20 @@
from chandra_aca.transform import radec_to_eci
from Quaternion import Quat
from ska_helpers.utils import LazyVal
from ska_helpers import chandra_models


CHANDRA_MODELS_PITCH_ROLL_FILE = "chandra_models/pitch_roll/pitch_roll_constraint.csv"


def load_roll_table():
dat = Table.read(Path(__file__).parent / "data" / "pitch_roll.fits.gz")
"""Load the pitch/roll table from the chandra_models repo."""
dat = chandra_models.get_data(
CHANDRA_MODELS_PITCH_ROLL_FILE, read_func=Table.read
)
# Sanity check that the pitch values are monotonically increasing.
assert np.all(np.diff(dat["pitch"]) > 0)

# Add a terminating row to the data such that for pitch at or greater
# than 180 the allowed roll deviation is defined as 0.
dat.add_row({"pitch": 180, "rolldev": 0})
return dat


Expand All @@ -28,17 +33,24 @@ def load_roll_table():

def allowed_rolldev(pitch):
"""Get allowed roll deviation (off-nominal roll) for the given ``pitch``.
:param pitch: Sun pitch angle (deg)
:returns: Roll deviation (deg)
This performs a linear interpolation of the values in the pitch/roll table in
the chandra_models repo in ``chandra_models/pitch_roll/pitch_roll_constraint.csv``.
For pitch values outside the range of the table the returned rolldev is 0.
:param pitch: float, ndarray
Sun pitch angle (deg)
:returns: float, ndarray
Roll deviation (deg)
"""
idx1 = np.searchsorted(ROLL_TABLE.val["pitch"], pitch, side="right")
idx0 = idx1 - 1
idx_max = len(ROLL_TABLE.val) - 1
idx0 = np.clip(idx0, 0, idx_max)
idx1 = np.clip(idx1, 0, idx_max)
val0 = ROLL_TABLE.val["rolldev"][idx0]
val1 = ROLL_TABLE.val["rolldev"][idx1]
out = np.minimum(val0, val1) # works even for a vector input for `pitch`
out = np.interp(
x=pitch,
xp=ROLL_TABLE.val["pitch"],
fp=ROLL_TABLE.val["off_nom_roll"],
left=0,
right=0,
)
return out


Expand Down
40 changes: 23 additions & 17 deletions ska_sun/tests/test_sun.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst

import numpy as np
import pytest
from Quaternion import Quat

from ..sun import (
Expand All @@ -13,30 +14,35 @@
from ..sun import pitch as sun_pitch
from ..sun import position


def test_allowed_rolldev():

# Test array of pitchs and allowed roll dev
testarr = [
[135, 13.979],
[138, 14.516],
# Expected pitch, rolldev pairs
exp_pitch_rolldev = np.array(
[
[0, 0],
[40, 0],
[179.9, 18.748772],
[179.997, 0],
[56.0, 0],
[85.49229, 4.95597],
[85.52, 4.9560848],
[124.99, 12.23652],
[125, 12.2380],
[135, 13.979],
[138, 14.516],
[179.9, 18.749],
[179.997, 18.749],
[180, 0],
[181, 0],
[85.49229, 13.677669],
[85.52, 18.756727],
[124.99, 18.748772],
[125, 17.0],
]
for pitch, rolldev in testarr:
assert np.isclose(allowed_rolldev(pitch), rolldev)
)

@pytest.mark.parametrize("pitch, rolldev", exp_pitch_rolldev)
def test_allowed_rolldev(pitch, rolldev):

# Test array of pitchs and allowed roll dev
assert np.isclose(allowed_rolldev(pitch), rolldev)


# Also test with pitch as vector
def test_allowed_rolldev_vector():
assert np.allclose(
allowed_rolldev(np.array(testarr)[:, 0]), np.array(testarr)[:, 1]
allowed_rolldev(exp_pitch_rolldev[:, 0]), exp_pitch_rolldev[:, 1]
)


Expand Down

0 comments on commit d963e45

Please sign in to comment.