jolly-roger 0.0.2__tar.gz → 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jolly-roger might be problematic. Click here for more details.
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.gitignore +1 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/PKG-INFO +1 -1
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/_version.py +2 -2
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/hour_angles.py +17 -20
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/uvws.py +12 -12
- jolly_roger-0.1.0/tests/test_hour_angles.py +16 -0
- jolly_roger-0.0.2/tests/test_hour_angles.py +0 -12
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.copier-answers.yml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.git_archival.txt +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.gitattributes +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.github/CONTRIBUTING.md +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.github/actions/setup-deps/action.yml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.github/dependabot.yml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.github/release.yml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.github/workflows/cd.yml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.github/workflows/ci.yml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.pre-commit-config.yaml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/.readthedocs.yaml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/LICENSE +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/README.md +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/docs/conf.py +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/docs/index.md +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/__init__.py +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/_version.pyi +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/baselines.py +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/flagger.py +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/logging.py +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/jolly_roger/py.typed +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/noxfile.py +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/pyproject.toml +0 -0
- {jolly_roger-0.0.2 → jolly_roger-0.1.0}/tests/test_package.py +0 -0
|
@@ -8,15 +8,14 @@ from typing import Literal
|
|
|
8
8
|
|
|
9
9
|
import astropy.units as u
|
|
10
10
|
import numpy as np
|
|
11
|
-
from astropy.coordinates import EarthLocation, SkyCoord, get_sun
|
|
11
|
+
from astropy.coordinates import AltAz, EarthLocation, SkyCoord, get_sun
|
|
12
12
|
from astropy.time import Time
|
|
13
13
|
from casacore.tables import table
|
|
14
14
|
|
|
15
15
|
from jolly_roger.logging import logger
|
|
16
16
|
|
|
17
17
|
# Default location with XYZ based on mean of antenna positions
|
|
18
|
-
|
|
19
|
-
ASKAP = EarthLocation(*ASKAP_XYZ_m)
|
|
18
|
+
ASKAP = EarthLocation.of_site("ASKAP")
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
@dataclass
|
|
@@ -75,6 +74,9 @@ def _process_position(
|
|
|
75
74
|
if position == "sun":
|
|
76
75
|
logger.info("Getting sky-position of the sun")
|
|
77
76
|
position = get_sun(times)
|
|
77
|
+
else:
|
|
78
|
+
logger.info(f"Getting sky-position of {position=}")
|
|
79
|
+
position = SkyCoord.from_name(position)
|
|
78
80
|
|
|
79
81
|
if position is None:
|
|
80
82
|
if ms_path is None:
|
|
@@ -83,8 +85,8 @@ def _process_position(
|
|
|
83
85
|
|
|
84
86
|
with table(str(ms_path / "FIELD")) as tab:
|
|
85
87
|
logger.info(f"Getting the sky-position from PHASE_DIR of {ms_path=}")
|
|
86
|
-
field_positions = tab.getcol("PHASE_DIR")
|
|
87
|
-
position = SkyCoord(field_positions
|
|
88
|
+
field_positions = tab.getcol("PHASE_DIR")[:]
|
|
89
|
+
position = SkyCoord(*(field_positions * u.rad).squeeze())
|
|
88
90
|
|
|
89
91
|
if isinstance(position, SkyCoord):
|
|
90
92
|
return position
|
|
@@ -116,7 +118,7 @@ def make_hour_angles_for_ms(
|
|
|
116
118
|
logger.info(f"Computing hour angles for {ms_path=}")
|
|
117
119
|
with table(str(ms_path), ack=False) as tab:
|
|
118
120
|
logger.info("Extracting timesteps and constructing time mapping")
|
|
119
|
-
times_mjds = tab.getcol("TIME_CENTROID")
|
|
121
|
+
times_mjds = tab.getcol("TIME_CENTROID")[:] * u.s
|
|
120
122
|
|
|
121
123
|
# get unique time steps and make sure they are in their first appeared order
|
|
122
124
|
times_mjds, indices = np.unique(times_mjds, return_index=True)
|
|
@@ -127,33 +129,28 @@ def make_hour_angles_for_ms(
|
|
|
127
129
|
if whole_day:
|
|
128
130
|
logger.info(f"Assuming a full day from {times_mjds} MJD (seconds)")
|
|
129
131
|
time_step = times_mjds[1] - times_mjds[0]
|
|
130
|
-
times_mjds =
|
|
131
|
-
|
|
132
|
+
times_mjds = np.arange(
|
|
133
|
+
start=times_mjds[0],
|
|
134
|
+
stop=times_mjds[0] + 24 * u.hour,
|
|
135
|
+
step=time_step,
|
|
132
136
|
)
|
|
133
137
|
|
|
134
|
-
times = Time(times_mjds
|
|
138
|
+
times = Time(times_mjds, format="mjd", scale="utc")
|
|
135
139
|
|
|
136
|
-
sky_position
|
|
137
|
-
position=position, times=times, ms_path=ms_path
|
|
138
|
-
)
|
|
140
|
+
sky_position = _process_position(position=position, times=times, ms_path=ms_path)
|
|
139
141
|
|
|
140
142
|
lst = times.sidereal_time("apparent", longitude=location.lon)
|
|
141
|
-
hour_angle = lst - sky_position.ra
|
|
142
|
-
mask = hour_angle > 12 * u.hourangle
|
|
143
|
-
hour_angle[mask] -= 24 * u.hourangle
|
|
143
|
+
hour_angle = (lst - sky_position.ra).wrap_at(12 * u.hourangle)
|
|
144
144
|
|
|
145
145
|
logger.info("Creatring elevation curve")
|
|
146
|
-
|
|
147
|
-
np.sin(location.lat) * np.sin(sky_position[0].dec.rad)
|
|
148
|
-
+ np.cos(location.lat) * np.cos(sky_position.dec.rad) * np.cos(hour_angle)
|
|
149
|
-
).to(u.rad)
|
|
146
|
+
altaz = sky_position.transform_to(AltAz(obstime=times, location=location))
|
|
150
147
|
|
|
151
148
|
return PositionHourAngles(
|
|
152
149
|
hour_angle=hour_angle,
|
|
153
150
|
time_mjds=times_mjds,
|
|
154
151
|
location=location,
|
|
155
152
|
position=sky_position,
|
|
156
|
-
elevation=
|
|
153
|
+
elevation=altaz.alt.to(u.rad),
|
|
157
154
|
time=times,
|
|
158
155
|
time_map=time_map,
|
|
159
156
|
)
|
|
@@ -44,12 +44,11 @@ def xyz_to_uvw(
|
|
|
44
44
|
"""
|
|
45
45
|
b_xyz = baselines.b_xyz
|
|
46
46
|
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
ha =
|
|
47
|
+
# Convert HA to geocentric hour angle (at Greenwich meridian)
|
|
48
|
+
# This is why we subtract the location's longitude
|
|
49
|
+
ha = hour_angles.hour_angle - hour_angles.location.lon
|
|
50
50
|
|
|
51
51
|
declination = hour_angles.position.dec
|
|
52
|
-
declination = declination.to(u.rad)
|
|
53
52
|
|
|
54
53
|
# This is necessary for broadcastung in the matrix to work.
|
|
55
54
|
# Should the position be a solar object like the sub its position
|
|
@@ -71,21 +70,22 @@ def xyz_to_uvw(
|
|
|
71
70
|
[sin_ha, cos_ha, zeros],
|
|
72
71
|
[-sin_dec * cos_ha, sin_dec * sin_ha, cos_dec],
|
|
73
72
|
[
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
cos_dec * cos_ha,
|
|
74
|
+
-cos_dec * sin_ha,
|
|
75
|
+
sin_dec,
|
|
77
76
|
],
|
|
78
77
|
]
|
|
79
78
|
)
|
|
80
79
|
|
|
81
80
|
# Every time this confuses me and I need the first mate to look over.
|
|
82
|
-
# b_xyz shape: (baselines,
|
|
81
|
+
# b_xyz shape: (baselines, 3) where coord is XYZ
|
|
83
82
|
# mat shape: (3, 3, timesteps)
|
|
84
|
-
# uvw shape: (
|
|
85
|
-
uvw = np.einsum("ijk,lj->
|
|
83
|
+
# uvw shape: (3, baseline, timesteps) where coord is UVW
|
|
84
|
+
uvw = np.einsum("ijk,lj->ilk", mat, b_xyz, optimize=True) # codespell:ignore ilk
|
|
85
|
+
# i,j,k -> (3, 3, time)
|
|
86
|
+
# l,j -> (baseline, 3)
|
|
87
|
+
# i,l,k -> (3, baseline, time)
|
|
86
88
|
|
|
87
|
-
# Make order (coord, baseline, timesteps)
|
|
88
|
-
uvw = np.swapaxes(uvw, 0, 1)
|
|
89
89
|
logger.debug(f"{uvw.shape=}")
|
|
90
90
|
|
|
91
91
|
return UVWs(uvws=uvw, hour_angles=hour_angles, baselines=baselines)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Some tests around the hour angles"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from astropy.coordinates import EarthLocation
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_askap_position() -> None:
|
|
9
|
+
"""Ensure that the EarthLocation for ASKAP is correctly formed"""
|
|
10
|
+
from jolly_roger.hour_angles import ASKAP
|
|
11
|
+
|
|
12
|
+
askap_astropy = EarthLocation.of_site("ASKAP")
|
|
13
|
+
|
|
14
|
+
assert ASKAP.x.value == askap_astropy.x.value
|
|
15
|
+
assert ASKAP.y.value == askap_astropy.y.value
|
|
16
|
+
assert ASKAP.z.value == askap_astropy.z.value
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"""Some tests around the hour angles"""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def test_askap_position() -> None:
|
|
7
|
-
"""Ensure that the EarthLocation for ASKAP is correctly formed"""
|
|
8
|
-
from jolly_roger.hour_angles import ASKAP
|
|
9
|
-
|
|
10
|
-
assert ASKAP.x.value == -2556146.66356375
|
|
11
|
-
assert ASKAP.y.value == 5097426.58592797
|
|
12
|
-
assert ASKAP.z.value == -2848333.08164107
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|