xradio 0.0.50__tar.gz → 0.0.51__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.
- {xradio-0.0.50/src/xradio.egg-info → xradio-0.0.51}/PKG-INFO +10 -4
- xradio-0.0.51/README.md +27 -0
- {xradio-0.0.50 → xradio-0.0.51}/pyproject.toml +5 -2
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/schema.py +2 -2
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/conversion.py +3 -3
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/create_antenna_xds.py +5 -5
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py +2 -1
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +151 -13
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/processing_set_xdt.py +146 -31
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/schema.py +40 -25
- {xradio-0.0.50 → xradio-0.0.51/src/xradio.egg-info}/PKG-INFO +10 -4
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio.egg-info/requires.txt +1 -1
- xradio-0.0.50/README.md +0 -21
- {xradio-0.0.50 → xradio-0.0.51}/LICENSE.txt +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/MANIFEST.in +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/setup.cfg +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/_casacore/tables.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/coord_math.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/dict_helpers.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/list_and_array.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/zarr/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/_utils/zarr/common.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_casacore/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_casacore/common.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_casacore/xds_from_casacore.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_casacore/xds_to_casacore.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_fits/xds_from_fits.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_zarr/common.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_zarr/xds_from_zarr.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_zarr/xds_to_zarr.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/_zarr/zarr_low_level.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/casacore.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/common.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/fits.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/image_factory.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/_util/zarr.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/image/image.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/load.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/table_query.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/write.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/chunks.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/descr.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv2_msv3.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/optimised_functions.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/partition_queries.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/partitions.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/subtables.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/cds.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/partition_attrs.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/stokes_types.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/xds_helper.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_zarr/encoding.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_zarr/read.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_zarr/write.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/msv2.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/zarr.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/convert_msv2_to_processing_set.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/load_processing_set.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/measurement_set_xdt.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/open_processing_set.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/schema/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/schema/bases.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/schema/check.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/schema/dataclass.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/schema/metamodel.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/schema/typing.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/sphinx/__init__.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio/sphinx/schema_table.py +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio.egg-info/SOURCES.txt +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio.egg-info/dependency_links.txt +0 -0
- {xradio-0.0.50 → xradio-0.0.51}/src/xradio.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xradio
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.51
|
|
4
4
|
Summary: Xarray Radio Astronomy Data IO
|
|
5
|
-
Author-email: Jan-Willem Steeb <jsteeb@nrao.edu>
|
|
5
|
+
Author-email: Jan-Willem Steeb <jsteeb@nrao.edu>, Federico Montesino Pouzols <pouzols@eso.edu>, Dave Mehringer <dmehring@nrao.edu>, Peter Wortmann <peter.wortmann@skao.int>
|
|
6
6
|
License: BSD 3-Clause License
|
|
7
7
|
|
|
8
8
|
All works in this repository are copyrighted 2024.
|
|
@@ -43,7 +43,7 @@ License-File: LICENSE.txt
|
|
|
43
43
|
Requires-Dist: astropy
|
|
44
44
|
Requires-Dist: dask
|
|
45
45
|
Requires-Dist: distributed
|
|
46
|
-
Requires-Dist: toolviper
|
|
46
|
+
Requires-Dist: toolviper>=0.0.11
|
|
47
47
|
Requires-Dist: numba>=0.57.0
|
|
48
48
|
Requires-Dist: numpy
|
|
49
49
|
Requires-Dist: pytest
|
|
@@ -79,7 +79,13 @@ Dynamic: license-file
|
|
|
79
79
|
# xradio
|
|
80
80
|
Xarray Radio Astronomy Data IO is still in development.
|
|
81
81
|
|
|
82
|
-
[](https://www.python.org/downloads/release/python-3130/)
|
|
83
|
+

|
|
84
|
+

|
|
85
|
+

|
|
86
|
+
[](https://codecov.io/gh/casangi/xradio/branch/main/xradio)
|
|
87
|
+
[](https://xradio.readthedocs.io)
|
|
88
|
+
[](https://pypi.python.org/pypi/xradio/)
|
|
83
89
|
|
|
84
90
|
# Installing
|
|
85
91
|
It is recommended to use the conda environment manager from [miniforge](https://github.com/conda-forge/miniforge) to create a clean, self-contained runtime where XRADIO and all its dependencies can be installed:
|
xradio-0.0.51/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# xradio
|
|
2
|
+
Xarray Radio Astronomy Data IO is still in development.
|
|
3
|
+
|
|
4
|
+
[](https://www.python.org/downloads/release/python-3130/)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
[](https://codecov.io/gh/casangi/xradio/branch/main/xradio)
|
|
9
|
+
[](https://xradio.readthedocs.io)
|
|
10
|
+
[](https://pypi.python.org/pypi/xradio/)
|
|
11
|
+
|
|
12
|
+
# Installing
|
|
13
|
+
It is recommended to use the conda environment manager from [miniforge](https://github.com/conda-forge/miniforge) to create a clean, self-contained runtime where XRADIO and all its dependencies can be installed:
|
|
14
|
+
```sh
|
|
15
|
+
conda create --name xradio python=3.12 --no-default-packages
|
|
16
|
+
conda activate xradio
|
|
17
|
+
```
|
|
18
|
+
> 📝 On macOS it is required to pre-install `python-casacore` using `conda install -c conda-forge python-casacore`.
|
|
19
|
+
|
|
20
|
+
XRADIO can now be installed using:
|
|
21
|
+
```sh
|
|
22
|
+
pip install xradio
|
|
23
|
+
```
|
|
24
|
+
This will also install the minimal dependencies for XRADIO. To install the minimal dependencies and the interactive components (JupyterLab) use:
|
|
25
|
+
```sh
|
|
26
|
+
pip install "xradio[interactive]"
|
|
27
|
+
```
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "xradio"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.51"
|
|
4
4
|
description = " Xarray Radio Astronomy Data IO"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Jan-Willem Steeb", email="jsteeb@nrao.edu"},
|
|
7
|
+
{name = "Federico Montesino Pouzols", email="pouzols@eso.edu"},
|
|
8
|
+
{name = "Dave Mehringer", email="dmehring@nrao.edu"},
|
|
9
|
+
{name = "Peter Wortmann", email="peter.wortmann@skao.int"}
|
|
7
10
|
]
|
|
8
11
|
license = {file = "LICENSE.txt"}
|
|
9
12
|
readme = "README.md"
|
|
@@ -13,7 +16,7 @@ dependencies = [
|
|
|
13
16
|
'astropy',
|
|
14
17
|
'dask',
|
|
15
18
|
'distributed',
|
|
16
|
-
'toolviper',
|
|
19
|
+
'toolviper>=0.0.11',
|
|
17
20
|
'numba>=0.57.0',
|
|
18
21
|
'numpy',
|
|
19
22
|
'pytest',
|
|
@@ -190,14 +190,14 @@ casacore_to_msv4_measure_type = {
|
|
|
190
190
|
"LSRK": "lsrk",
|
|
191
191
|
"LSRD": "lsrd",
|
|
192
192
|
"BARY": "BARY",
|
|
193
|
-
"GEO": "
|
|
193
|
+
"GEO": "gcrs",
|
|
194
194
|
"TOPO": "TOPO",
|
|
195
195
|
}, # The frames/observer we are not sure if/how to translate to astropy are uppercase
|
|
196
196
|
},
|
|
197
197
|
"position": {
|
|
198
198
|
"type": "location",
|
|
199
199
|
"Ref": "frame",
|
|
200
|
-
"Ref_map": {"ITRF": "
|
|
200
|
+
"Ref_map": {"ITRF": "ITRS"},
|
|
201
201
|
},
|
|
202
202
|
"uvw": {
|
|
203
203
|
"type": "uvw",
|
|
@@ -1214,13 +1214,13 @@ def convert_and_write_partition(
|
|
|
1214
1214
|
)
|
|
1215
1215
|
# but before, keep the name-id arrays, we need them for the pointing and weather xds
|
|
1216
1216
|
ant_xds_name_ids = ant_xds["antenna_name"].set_xindex("antenna_id")
|
|
1217
|
-
|
|
1217
|
+
ant_position_xds_with_ids = ant_xds["ANTENNA_POSITION"].set_xindex("antenna_id")
|
|
1218
1218
|
# No longer needed after converting to name.
|
|
1219
1219
|
ant_xds = ant_xds.drop_vars("antenna_id")
|
|
1220
1220
|
|
|
1221
1221
|
# Create weather_xds
|
|
1222
1222
|
start = time.time()
|
|
1223
|
-
weather_xds = create_weather_xds(in_file,
|
|
1223
|
+
weather_xds = create_weather_xds(in_file, ant_position_xds_with_ids)
|
|
1224
1224
|
logger.debug("Time weather " + str(time.time() - start))
|
|
1225
1225
|
|
|
1226
1226
|
# Create pointing_xds
|
|
@@ -1425,7 +1425,7 @@ def antenna_ids_to_names(
|
|
|
1425
1425
|
"antenna_id",
|
|
1426
1426
|
"antenna_name",
|
|
1427
1427
|
"mount",
|
|
1428
|
-
"
|
|
1428
|
+
"station_name",
|
|
1429
1429
|
]
|
|
1430
1430
|
for unwanted_coord in unwanted_coords_from_ant_xds:
|
|
1431
1431
|
xds = xds.drop_vars(unwanted_coord)
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/create_antenna_xds.py
RENAMED
|
@@ -109,7 +109,7 @@ def extract_antenna_info(
|
|
|
109
109
|
|
|
110
110
|
to_new_coords = {
|
|
111
111
|
"NAME": ["antenna_name", ["antenna_name"]],
|
|
112
|
-
"STATION": ["
|
|
112
|
+
"STATION": ["station_name", ["antenna_name"]],
|
|
113
113
|
"MOUNT": ["mount", ["antenna_name"]],
|
|
114
114
|
# "PHASED_ARRAY_ID": ["phased_array_id", ["antenna_name"]],
|
|
115
115
|
"antenna_id": ["antenna_id", ["antenna_name"]],
|
|
@@ -158,9 +158,9 @@ def extract_antenna_info(
|
|
|
158
158
|
|
|
159
159
|
# None of the native numpy functions work on the github test runner.
|
|
160
160
|
antenna_name = ant_xds["antenna_name"].values
|
|
161
|
-
|
|
161
|
+
station_name = ant_xds["station_name"].values
|
|
162
162
|
antenna_name = np.array(
|
|
163
|
-
list(map(lambda x, y: x + "_" + y, antenna_name,
|
|
163
|
+
list(map(lambda x, y: x + "_" + y, antenna_name, station_name))
|
|
164
164
|
)
|
|
165
165
|
|
|
166
166
|
ant_xds["antenna_name"] = xr.DataArray(antenna_name, dims=["antenna_name"])
|
|
@@ -376,7 +376,7 @@ def create_gain_curve_xds(
|
|
|
376
376
|
|
|
377
377
|
ant_borrowed_coords = {
|
|
378
378
|
"antenna_name": ant_xds.coords["antenna_name"],
|
|
379
|
-
"
|
|
379
|
+
"station_name": ant_xds.coords["station_name"],
|
|
380
380
|
"mount": ant_xds.coords["mount"],
|
|
381
381
|
"telescope_name": ant_xds.coords["telescope_name"],
|
|
382
382
|
"receptor_label": ant_xds.coords["receptor_label"],
|
|
@@ -486,7 +486,7 @@ def create_phase_calibration_xds(
|
|
|
486
486
|
|
|
487
487
|
ant_borrowed_coords = {
|
|
488
488
|
"antenna_name": ant_xds.coords["antenna_name"],
|
|
489
|
-
"
|
|
489
|
+
"station_name": ant_xds.coords["station_name"],
|
|
490
490
|
"mount": ant_xds.coords["mount"],
|
|
491
491
|
"telescope_name": ant_xds.coords["telescope_name"],
|
|
492
492
|
"receptor_label": ant_xds.coords["receptor_label"],
|
|
@@ -226,9 +226,10 @@ def extract_ephemeris_info(
|
|
|
226
226
|
"type": "location",
|
|
227
227
|
"units": ["deg", "deg", "m"],
|
|
228
228
|
"data": observer_position,
|
|
229
|
-
"frame": "
|
|
229
|
+
"frame": "ITRS",
|
|
230
230
|
"origin_object_name": "Earth",
|
|
231
231
|
"coordinate_system": ephemeris_meta["obsloc"].lower(),
|
|
232
|
+
"ellipsoid": "WGS84",
|
|
232
233
|
}
|
|
233
234
|
) # I think the units are ['deg','deg','m'] and 'WGS84'.
|
|
234
235
|
|
|
@@ -172,7 +172,130 @@ def make_taql_where_weather(
|
|
|
172
172
|
return taql_where
|
|
173
173
|
|
|
174
174
|
|
|
175
|
-
def
|
|
175
|
+
def prepare_generic_weather_xds_and_station_name(
|
|
176
|
+
generic_weather_xds: xr.Dataset,
|
|
177
|
+
in_file: str,
|
|
178
|
+
ant_position_with_ids: xr.DataArray,
|
|
179
|
+
has_asdm_station_position: bool,
|
|
180
|
+
) -> tuple[xr.Dataset, np.ndarray]:
|
|
181
|
+
"""
|
|
182
|
+
A generic_weather_xds loaded with load_generic_table() might still need to be reloaded
|
|
183
|
+
with an additional WHERE condition to constrain the indices of antennas. But this depends on whether
|
|
184
|
+
ASDM/importasdm extension columns are present or not.
|
|
185
|
+
|
|
186
|
+
This also prepares the station_name values:
|
|
187
|
+
- if has_asdm_station_ids:
|
|
188
|
+
- tries to find from ASDM_STATION the station names,
|
|
189
|
+
- otherwise, takes ids (antenna_ids in generic_weather were actually the ASDM_STATION_IDs
|
|
190
|
+
- else: get the values from antenna_xds (the stations present)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
Parameters
|
|
194
|
+
----------
|
|
195
|
+
generic_weather_xds : xr.Dataset
|
|
196
|
+
generic dataset read from an MSv2 WEATHER subtable
|
|
197
|
+
in_file : str
|
|
198
|
+
Input MS name.
|
|
199
|
+
ant_position_with_ids : xr.DataArray
|
|
200
|
+
antenna_position data var from the antenna_xds (expected to still include the initial ANTENNA_ID
|
|
201
|
+
coordinate as well as other coordinates from the antenna_xds)
|
|
202
|
+
has_asdm_station_position : bool
|
|
203
|
+
wHether this generic weatehr_xds should be treated as including the nonstandard extensions
|
|
204
|
+
NS_WX_STATION_ID and NS_WX_STATION_POSITION as created by CASA/importasdm (ALMA and VLA).
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
(generic_weather_xds, station_name): tuple[[xarray.Dataset, numpy.ndarray]
|
|
209
|
+
Weather Xarray Dataset prepared for generic conversion to MSv4, values for the station_name coordinate
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
if has_asdm_station_position:
|
|
213
|
+
asdm_station_path = os.path.join(in_file, "ASDM_STATION")
|
|
214
|
+
if table_exists(asdm_station_path):
|
|
215
|
+
asdm_station_xds = load_generic_table(in_file, "ASDM_STATION")
|
|
216
|
+
station_name = asdm_station_xds.name.values[
|
|
217
|
+
generic_weather_xds["ANTENNA_ID"].values
|
|
218
|
+
]
|
|
219
|
+
else:
|
|
220
|
+
# if no info from ASDM_STATION, use the indices from antenna_id which was actually the NS_WX_STATION_ID
|
|
221
|
+
len_antenna_id = generic_weather_xds.sizes["ANTENNA_ID"]
|
|
222
|
+
station_name = list(
|
|
223
|
+
map(
|
|
224
|
+
lambda x, y: x + "_" + y,
|
|
225
|
+
["Station"] * len_antenna_id,
|
|
226
|
+
generic_weather_xds["ANTENNA_ID"].values.astype(str),
|
|
227
|
+
)
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
else:
|
|
231
|
+
taql_where = make_taql_where_weather(in_file, ant_position_with_ids)
|
|
232
|
+
generic_weather_xds = load_generic_table(
|
|
233
|
+
in_file,
|
|
234
|
+
"WEATHER",
|
|
235
|
+
rename_ids=subt_rename_ids["WEATHER"],
|
|
236
|
+
taql_where=taql_where,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
if not generic_weather_xds.data_vars:
|
|
240
|
+
# for example when the weather subtable only has info for antennas/stations
|
|
241
|
+
# not present in the MSv4 (no overlap between antennas loaded in ant_xds and weather)
|
|
242
|
+
return None, None
|
|
243
|
+
|
|
244
|
+
stations_present = ant_position_with_ids.sel(
|
|
245
|
+
antenna_id=generic_weather_xds["ANTENNA_ID"]
|
|
246
|
+
).station_name
|
|
247
|
+
station_name = stations_present.values
|
|
248
|
+
|
|
249
|
+
return generic_weather_xds, station_name
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def finalize_station_position(
|
|
253
|
+
weather_xds: xr.Dataset, ant_position_with_ids, has_asdm_station_position: bool
|
|
254
|
+
) -> xr.Dataset:
|
|
255
|
+
"""
|
|
256
|
+
For a STATION_POSITION data var being added to a weather_xds, make sure coordinates and dimensions
|
|
257
|
+
are conforming to the schema.
|
|
258
|
+
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
weather_xds : xr.Dataset
|
|
262
|
+
weather_xds where we still need to ensure the right coordinates and attributes
|
|
263
|
+
ant_position_with_ids : xr.DataArray
|
|
264
|
+
antenna_position data var from the antenna_xds (expected to still include the initial ANTENNA_ID
|
|
265
|
+
coordinate as well as other coordinates from the antenna_xds)
|
|
266
|
+
has_asdm_station_position : bool
|
|
267
|
+
Whether this generic weatehr_xds should be treated as including the nonstandard extensions
|
|
268
|
+
NS_WX_STATION_ID and NS_WX_STATION_POSITION as created by CASA/importasdm (ALMA and VLA).
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
weather_xds: xarray.Dataset
|
|
273
|
+
Weather Xarray Dataset with all coordinates and attributes in STATION_POSITION
|
|
274
|
+
"""
|
|
275
|
+
if has_asdm_station_position:
|
|
276
|
+
# STATION_POSITION has been created but needs prooper dimensions and attrs
|
|
277
|
+
# Drop the time dim
|
|
278
|
+
weather_xds["STATION_POSITION"] = weather_xds["STATION_POSITION"].sel(
|
|
279
|
+
time_weather=0, drop=True, method="nearest"
|
|
280
|
+
)
|
|
281
|
+
# borrow location frame attributes from antenna position
|
|
282
|
+
weather_xds["STATION_POSITION"].attrs = ant_position_with_ids.attrs
|
|
283
|
+
else:
|
|
284
|
+
# borrow from ant_posision_with_ids but without carrying over other coords
|
|
285
|
+
weather_xds = weather_xds.assign(
|
|
286
|
+
{
|
|
287
|
+
"STATION_POSITION": (
|
|
288
|
+
["station_name", "cartesian_pos_label"],
|
|
289
|
+
ant_position_with_ids.values,
|
|
290
|
+
ant_position_with_ids.attrs,
|
|
291
|
+
)
|
|
292
|
+
}
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
return weather_xds
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def create_weather_xds(in_file: str, ant_position_with_ids: xr.DataArray):
|
|
176
299
|
"""
|
|
177
300
|
Creates a Weather Xarray Dataset from a MS v2 WEATHER table.
|
|
178
301
|
|
|
@@ -180,8 +303,9 @@ def create_weather_xds(in_file: str, ant_xds_station_name_ids: xr.DataArray):
|
|
|
180
303
|
----------
|
|
181
304
|
in_file : str
|
|
182
305
|
Input MS name.
|
|
183
|
-
|
|
184
|
-
|
|
306
|
+
ant_position_with_ids : xr.DataArray
|
|
307
|
+
antenna_position data var from the antenna_xds (expected to still including the initial ANTENNA_ID coordinate
|
|
308
|
+
as wellas other coordinates from the antenna_xds)
|
|
185
309
|
|
|
186
310
|
Returns
|
|
187
311
|
-------
|
|
@@ -190,32 +314,32 @@ def create_weather_xds(in_file: str, ant_xds_station_name_ids: xr.DataArray):
|
|
|
190
314
|
"""
|
|
191
315
|
|
|
192
316
|
try:
|
|
193
|
-
taql_where = make_taql_where_weather(in_file, ant_xds_station_name_ids)
|
|
194
317
|
generic_weather_xds = load_generic_table(
|
|
195
318
|
in_file,
|
|
196
319
|
"WEATHER",
|
|
197
320
|
rename_ids=subt_rename_ids["WEATHER"],
|
|
198
|
-
taql_where=taql_where,
|
|
199
321
|
)
|
|
200
322
|
except ValueError as _exc:
|
|
201
323
|
return None
|
|
202
324
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
325
|
+
has_asdm_station_position = (
|
|
326
|
+
"NS_WX_STATION_POSITION" in generic_weather_xds.data_vars
|
|
327
|
+
)
|
|
328
|
+
generic_weather_xds, station_name = prepare_generic_weather_xds_and_station_name(
|
|
329
|
+
generic_weather_xds, in_file, ant_position_with_ids, has_asdm_station_position
|
|
330
|
+
)
|
|
331
|
+
if not generic_weather_xds:
|
|
206
332
|
return None
|
|
207
333
|
|
|
208
334
|
weather_xds = xr.Dataset(attrs={"type": "weather"})
|
|
209
|
-
stations_present = ant_xds_station_name_ids.sel(
|
|
210
|
-
antenna_id=generic_weather_xds["ANTENNA_ID"]
|
|
211
|
-
)
|
|
212
335
|
coords = {
|
|
213
|
-
"station_name":
|
|
214
|
-
"
|
|
336
|
+
"station_name": station_name,
|
|
337
|
+
"cartesian_pos_label": ["x", "y", "z"],
|
|
215
338
|
}
|
|
216
339
|
weather_xds = weather_xds.assign_coords(coords)
|
|
217
340
|
|
|
218
341
|
dims_station_time = ["station_name", "time_weather"]
|
|
342
|
+
dims_station_time_position = dims_station_time + ["cartesian_pos_label"]
|
|
219
343
|
to_new_data_variables = {
|
|
220
344
|
"H20": ["H2O", dims_station_time],
|
|
221
345
|
"IONOS_ELECTRON": ["IONOS_ELECTRON", dims_station_time],
|
|
@@ -226,6 +350,15 @@ def create_weather_xds(in_file: str, ant_xds_station_name_ids: xr.DataArray):
|
|
|
226
350
|
"WIND_DIRECTION": ["WIND_DIRECTION", dims_station_time],
|
|
227
351
|
"WIND_SPEED": ["WIND_SPEED", dims_station_time],
|
|
228
352
|
}
|
|
353
|
+
if has_asdm_station_position:
|
|
354
|
+
to_new_data_variables.update(
|
|
355
|
+
{
|
|
356
|
+
"NS_WX_STATION_POSITION": [
|
|
357
|
+
"STATION_POSITION",
|
|
358
|
+
dims_station_time_position,
|
|
359
|
+
],
|
|
360
|
+
}
|
|
361
|
+
)
|
|
229
362
|
|
|
230
363
|
to_new_coords = {
|
|
231
364
|
"TIME": ["time_weather", ["time_weather"]],
|
|
@@ -234,6 +367,9 @@ def create_weather_xds(in_file: str, ant_xds_station_name_ids: xr.DataArray):
|
|
|
234
367
|
weather_xds = convert_generic_xds_to_xradio_schema(
|
|
235
368
|
generic_weather_xds, weather_xds, to_new_data_variables, to_new_coords
|
|
236
369
|
)
|
|
370
|
+
weather_xds = finalize_station_position(
|
|
371
|
+
weather_xds, ant_position_with_ids, has_asdm_station_position
|
|
372
|
+
)
|
|
237
373
|
|
|
238
374
|
# TODO: option to interpolate to main time
|
|
239
375
|
|
|
@@ -256,6 +392,7 @@ def correct_generic_pointing_xds(
|
|
|
256
392
|
and tries to correct several deviations from the MSv2 specs seen in
|
|
257
393
|
common test data.
|
|
258
394
|
The problems fixed here include wrong dimensions:
|
|
395
|
+
|
|
259
396
|
- for example transposed dimensions with respect to the MSv2 specs (output
|
|
260
397
|
from CASA simulator),
|
|
261
398
|
- missing/additional unexpected dimensions when some of the columns are
|
|
@@ -423,6 +560,7 @@ def prepare_generic_sys_cal_xds(generic_sys_cal_xds: xr.Dataset) -> xr.Dataset:
|
|
|
423
560
|
sys_cal_xds dataset, as their structure differs in dimensions and order
|
|
424
561
|
of dimensions.
|
|
425
562
|
This function performs various prepareation steps, such as:
|
|
563
|
+
|
|
426
564
|
- filter out dimensions not neeed for an individual MSv4 (SPW, FEED),
|
|
427
565
|
- drop variables loaded from columns with all items set to empty array,
|
|
428
566
|
- transpose the dimensions frequency,receptor
|
|
@@ -569,6 +569,17 @@ class ProcessingSetXdt:
|
|
|
569
569
|
ValueError
|
|
570
570
|
If the combined datasets are empty or improperly formatted.
|
|
571
571
|
"""
|
|
572
|
+
|
|
573
|
+
def setup_annotations_all(axis, scatter, field_names):
|
|
574
|
+
"""
|
|
575
|
+
Creates annotations for when label_all_fields=True
|
|
576
|
+
"""
|
|
577
|
+
coord_x, coord_y = np.array(scatter.get_offsets()).transpose()
|
|
578
|
+
offset_x = np.abs(np.max(coord_x) - np.min(coord_x)) * 0.01
|
|
579
|
+
offset_y = np.abs(np.max(coord_y) - np.min(coord_y)) * 0.01
|
|
580
|
+
for idx, (x, y) in enumerate(zip(coord_x + offset_x, coord_y + offset_y)):
|
|
581
|
+
axis.annotate(field_names[idx], (x, y), alpha=1)
|
|
582
|
+
|
|
572
583
|
if self._xdt.attrs.get("type") not in PS_DATASET_TYPES:
|
|
573
584
|
raise InvalidAccessorLocation(
|
|
574
585
|
f"{self._xdt.path} is not a processing set node."
|
|
@@ -585,9 +596,9 @@ class ProcessingSetXdt:
|
|
|
585
596
|
if (len(combined_field_and_source_xds.data_vars) > 0) and (
|
|
586
597
|
"FIELD_PHASE_CENTER" in combined_field_and_source_xds
|
|
587
598
|
):
|
|
588
|
-
plt.figure()
|
|
599
|
+
fig = plt.figure()
|
|
589
600
|
plt.title("Field Phase Center Locations")
|
|
590
|
-
plt.scatter(
|
|
601
|
+
scatter = plt.scatter(
|
|
591
602
|
combined_field_and_source_xds["FIELD_PHASE_CENTER"].sel(
|
|
592
603
|
sky_dir_label="ra"
|
|
593
604
|
),
|
|
@@ -595,31 +606,40 @@ class ProcessingSetXdt:
|
|
|
595
606
|
sky_dir_label="dec"
|
|
596
607
|
),
|
|
597
608
|
)
|
|
598
|
-
|
|
599
609
|
center_field_name = combined_field_and_source_xds.attrs["center_field_name"]
|
|
600
610
|
center_field = combined_field_and_source_xds.sel(
|
|
601
611
|
field_name=center_field_name
|
|
602
612
|
)
|
|
613
|
+
|
|
614
|
+
if label_all_fields:
|
|
615
|
+
field_name = combined_field_and_source_xds.field_name.values
|
|
616
|
+
setup_annotations_all(fig.axes[0], scatter, field_name)
|
|
617
|
+
fig.axes[0].margins(0.2, 0.2)
|
|
618
|
+
center_label = None
|
|
619
|
+
else:
|
|
620
|
+
center_label = center_field_name
|
|
621
|
+
|
|
603
622
|
plt.scatter(
|
|
604
623
|
center_field["FIELD_PHASE_CENTER"].sel(sky_dir_label="ra"),
|
|
605
624
|
center_field["FIELD_PHASE_CENTER"].sel(sky_dir_label="dec"),
|
|
606
625
|
color="red",
|
|
607
|
-
label=
|
|
626
|
+
label=center_label,
|
|
608
627
|
)
|
|
609
628
|
plt.xlabel("RA (rad)")
|
|
610
629
|
plt.ylabel("DEC (rad)")
|
|
611
|
-
|
|
630
|
+
if not label_all_fields:
|
|
631
|
+
plt.legend()
|
|
612
632
|
plt.show()
|
|
613
633
|
|
|
614
634
|
if (len(combined_ephemeris_field_and_source_xds.data_vars) > 0) and (
|
|
615
635
|
"FIELD_PHASE_CENTER" in combined_ephemeris_field_and_source_xds
|
|
616
636
|
):
|
|
617
637
|
|
|
618
|
-
plt.figure()
|
|
638
|
+
fig = plt.figure()
|
|
619
639
|
plt.title(
|
|
620
640
|
"Offset of Field Phase Center from Source Location (Ephemeris Data)"
|
|
621
641
|
)
|
|
622
|
-
plt.scatter(
|
|
642
|
+
scatter = plt.scatter(
|
|
623
643
|
combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].sel(
|
|
624
644
|
sky_dir_label="ra"
|
|
625
645
|
),
|
|
@@ -639,15 +659,26 @@ class ProcessingSetXdt:
|
|
|
639
659
|
center_field = combined_ephemeris_field_and_source_xds.sel(
|
|
640
660
|
field_name=center_field_name
|
|
641
661
|
)
|
|
662
|
+
|
|
663
|
+
if label_all_fields:
|
|
664
|
+
field_name = combined_ephemeris_field_and_source_xds.field_name.values
|
|
665
|
+
setup_annotations_all(fig.axes[0], scatter, field_name)
|
|
666
|
+
fig.axes[0].margins(0.2, 0.2)
|
|
667
|
+
center_label = None
|
|
668
|
+
else:
|
|
669
|
+
center_label = center_field_name
|
|
670
|
+
|
|
642
671
|
plt.scatter(
|
|
643
672
|
center_field["FIELD_OFFSET"].sel(sky_dir_label="ra"),
|
|
644
673
|
center_field["FIELD_OFFSET"].sel(sky_dir_label="dec"),
|
|
645
674
|
color="red",
|
|
646
|
-
label=
|
|
675
|
+
label=center_label,
|
|
647
676
|
)
|
|
677
|
+
|
|
648
678
|
plt.xlabel("RA Offset (rad)")
|
|
649
679
|
plt.ylabel("DEC Offset (rad)")
|
|
650
|
-
|
|
680
|
+
if not label_all_fields:
|
|
681
|
+
plt.legend()
|
|
651
682
|
plt.show()
|
|
652
683
|
|
|
653
684
|
def get_combined_antenna_xds(self) -> xr.Dataset:
|
|
@@ -693,18 +724,23 @@ class ProcessingSetXdt:
|
|
|
693
724
|
|
|
694
725
|
return combined_antenna_xds
|
|
695
726
|
|
|
696
|
-
def plot_antenna_positions(self):
|
|
727
|
+
def plot_antenna_positions(self, label_all_antennas: bool = False):
|
|
697
728
|
"""
|
|
698
729
|
Plot the antenna positions of all antennas in the Processing Set.
|
|
699
730
|
|
|
700
|
-
This method generates three scatter plots displaying the antenna
|
|
731
|
+
This method generates and displays a figure with three scatter plots, displaying the antenna
|
|
732
|
+
positions in different planes:
|
|
733
|
+
|
|
701
734
|
- X vs Y
|
|
702
735
|
- X vs Z
|
|
703
736
|
- Y vs Z
|
|
704
737
|
|
|
738
|
+
The antenna names are shown on hovering their positions, unless label_all_antennas is enabled.
|
|
739
|
+
|
|
705
740
|
Parameters
|
|
706
741
|
----------
|
|
707
|
-
|
|
742
|
+
label_all_antennas : bool, optional
|
|
743
|
+
If 'True', annotations are shown with the names of every antenna next to their positions.
|
|
708
744
|
|
|
709
745
|
Returns
|
|
710
746
|
-------
|
|
@@ -715,6 +751,75 @@ class ProcessingSetXdt:
|
|
|
715
751
|
ValueError
|
|
716
752
|
If the combined antenna dataset is empty or missing required coordinates.
|
|
717
753
|
"""
|
|
754
|
+
|
|
755
|
+
def antenna_hover(event):
|
|
756
|
+
if event.inaxes in antenna_axes:
|
|
757
|
+
for axis in antenna_axes:
|
|
758
|
+
contained, indices = scatter_map[axis].contains(event)
|
|
759
|
+
annotation = annotations_map[axis]
|
|
760
|
+
if contained:
|
|
761
|
+
scatter = scatter_map[axis]
|
|
762
|
+
update_antenna_annotation(indices, scatter, annotation)
|
|
763
|
+
annotation.set_visible(True)
|
|
764
|
+
fig.canvas.draw_idle()
|
|
765
|
+
else:
|
|
766
|
+
visible = annotation.get_visible()
|
|
767
|
+
if visible:
|
|
768
|
+
annotation.set_visible(False)
|
|
769
|
+
fig.canvas.draw_idle()
|
|
770
|
+
|
|
771
|
+
def update_antenna_annotation(indices, scatter, annotation):
|
|
772
|
+
position = scatter.get_offsets()[indices["ind"][0]]
|
|
773
|
+
annotation.xy = position
|
|
774
|
+
text = "{}".format(" ".join([antenna_names[num] for num in indices["ind"]]))
|
|
775
|
+
annotation.set_text(text)
|
|
776
|
+
annotation.get_bbox_patch().set_facecolor("#e8d192")
|
|
777
|
+
annotation.get_bbox_patch().set_alpha(1)
|
|
778
|
+
|
|
779
|
+
def setup_annotations_for_hover(antenna_axes, scatter_plots):
|
|
780
|
+
"""
|
|
781
|
+
Creates annotations on all the axes requested.
|
|
782
|
+
|
|
783
|
+
Returns
|
|
784
|
+
-------
|
|
785
|
+
dict
|
|
786
|
+
dict from antenna axes -> annotation objects
|
|
787
|
+
"""
|
|
788
|
+
antenna_annotations = []
|
|
789
|
+
for axis in antenna_axes:
|
|
790
|
+
annotation = axis.annotate(
|
|
791
|
+
"",
|
|
792
|
+
xy=(0, 0),
|
|
793
|
+
xytext=(10, 15),
|
|
794
|
+
textcoords="offset points",
|
|
795
|
+
arrowprops=dict(arrowstyle="-|>"),
|
|
796
|
+
bbox=dict(boxstyle="round", fc="w"),
|
|
797
|
+
)
|
|
798
|
+
antenna_annotations.append(annotation)
|
|
799
|
+
annotation.set_visible(False)
|
|
800
|
+
annotations_map = dict(zip(antenna_axes, antenna_annotations))
|
|
801
|
+
|
|
802
|
+
return annotations_map
|
|
803
|
+
|
|
804
|
+
def setup_annotations_for_all(antenna_axes, scatter_map):
|
|
805
|
+
"""
|
|
806
|
+
Creates annotations for when label_all_antennas=True
|
|
807
|
+
"""
|
|
808
|
+
antenna_annotations = []
|
|
809
|
+
for axis in antenna_axes:
|
|
810
|
+
scatter = scatter_map[axis]
|
|
811
|
+
coord_x, coord_y = np.array(scatter.get_offsets()).transpose()
|
|
812
|
+
offset_x = np.abs(np.max(coord_x) - np.min(coord_x)) * 0.01
|
|
813
|
+
offset_y = np.abs(np.max(coord_y) - np.min(coord_y)) * 0.01
|
|
814
|
+
for idx, (x, y) in enumerate(
|
|
815
|
+
zip(coord_x + offset_x, coord_y + offset_y)
|
|
816
|
+
):
|
|
817
|
+
annotation = axis.annotate(
|
|
818
|
+
antenna_names[idx],
|
|
819
|
+
(x, y),
|
|
820
|
+
alpha=1,
|
|
821
|
+
)
|
|
822
|
+
|
|
718
823
|
if self._xdt.attrs.get("type") not in PS_DATASET_TYPES:
|
|
719
824
|
raise InvalidAccessorLocation(
|
|
720
825
|
f"{self._xdt.path} is not a processing set node."
|
|
@@ -723,34 +828,44 @@ class ProcessingSetXdt:
|
|
|
723
828
|
combined_antenna_xds = self.get_combined_antenna_xds()
|
|
724
829
|
from matplotlib import pyplot as plt
|
|
725
830
|
|
|
726
|
-
plt.
|
|
727
|
-
|
|
728
|
-
|
|
831
|
+
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 8))
|
|
832
|
+
fig.suptitle("Antenna Positions")
|
|
833
|
+
fig.subplots_adjust(
|
|
834
|
+
wspace=0.25, hspace=0.25, left=0.1, right=0.95, top=0.9, bottom=0.1
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
scatter1 = ax1.scatter(
|
|
729
838
|
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="x"),
|
|
730
839
|
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="y"),
|
|
731
840
|
)
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
841
|
+
ax1.set_xlabel("x (m)")
|
|
842
|
+
ax1.set_ylabel("y (m)")
|
|
843
|
+
antenna_names = combined_antenna_xds.antenna_name.values
|
|
735
844
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
plt.scatter(
|
|
739
|
-
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="x"),
|
|
845
|
+
scatter2 = ax2.scatter(
|
|
846
|
+
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="y"),
|
|
740
847
|
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="z"),
|
|
741
848
|
)
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
plt.show()
|
|
849
|
+
ax2.set_xlabel("y (m)")
|
|
850
|
+
ax2.set_ylabel("z (m)")
|
|
745
851
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
plt.scatter(
|
|
749
|
-
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="y"),
|
|
852
|
+
scatter3 = ax3.scatter(
|
|
853
|
+
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="x"),
|
|
750
854
|
combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="z"),
|
|
751
855
|
)
|
|
752
|
-
|
|
753
|
-
|
|
856
|
+
ax3.set_xlabel("x (m)")
|
|
857
|
+
ax3.set_ylabel("z (m)")
|
|
858
|
+
|
|
859
|
+
ax4.axis("off")
|
|
860
|
+
|
|
861
|
+
antenna_axes = [ax1, ax2, ax3]
|
|
862
|
+
scatter_map = dict(zip(antenna_axes, [scatter1, scatter2, scatter3]))
|
|
863
|
+
if label_all_antennas:
|
|
864
|
+
annotations_map = setup_annotations_for_all(antenna_axes, scatter_map)
|
|
865
|
+
else:
|
|
866
|
+
annotations_map = setup_annotations_for_hover(antenna_axes, scatter_map)
|
|
867
|
+
fig.canvas.mpl_connect("motion_notify_event", antenna_hover)
|
|
868
|
+
|
|
754
869
|
plt.show()
|
|
755
870
|
|
|
756
871
|
|
|
@@ -27,7 +27,7 @@ TimeWeather = Literal["time_weather"]
|
|
|
27
27
|
AntennaName = Literal["antenna_name"]
|
|
28
28
|
""" Antenna name dimension """
|
|
29
29
|
StationName = Literal["station_name"]
|
|
30
|
-
""" Station
|
|
30
|
+
""" Station name dimension """
|
|
31
31
|
ReceptorLabel = Literal["receptor_label"]
|
|
32
32
|
""" Receptor label dimension """
|
|
33
33
|
ToneLabel = Literal["tone_label"]
|
|
@@ -295,7 +295,7 @@ class SkyCoordArray:
|
|
|
295
295
|
|
|
296
296
|
type: Attr[SkyCoord] = "sky_coord"
|
|
297
297
|
units: Attr[UnitsOfSkyCoordInRadians] = ("rad", "rad")
|
|
298
|
-
frame: Attr[AllowedSkyCoordFrames] = ""
|
|
298
|
+
frame: Attr[AllowedSkyCoordFrames] = "icrs"
|
|
299
299
|
"""
|
|
300
300
|
Possible values are astropy SkyCoord frames.
|
|
301
301
|
Several casacore frames found in MSv2 are translated to astropy frames as follows: AZELGEO=>altaz, J2000=>fk5, ICRS=>icrs.
|
|
@@ -324,7 +324,7 @@ class PointingBeamArray:
|
|
|
324
324
|
|
|
325
325
|
type: Attr[SkyCoord] = "sky_coord"
|
|
326
326
|
units: Attr[UnitsOfSkyCoordInRadians] = ("rad", "rad")
|
|
327
|
-
frame: Attr[AllowedSkyCoordFrames] = "
|
|
327
|
+
frame: Attr[AllowedSkyCoordFrames] = "icrs"
|
|
328
328
|
"""
|
|
329
329
|
From fixvis docs: clean and the im tool ignore the reference frame claimed by the UVW column (it is often mislabelled
|
|
330
330
|
as ITRF when it is really FK5 (J2000)) and instead assume the (u, v, w)s are in the same frame as the phase tracking
|
|
@@ -341,7 +341,7 @@ class LocalSkyCoordArray:
|
|
|
341
341
|
|
|
342
342
|
type: Attr[SkyCoord] = "sky_coord"
|
|
343
343
|
units: Attr[UnitsOfSkyCoordInRadians] = ("rad", "rad")
|
|
344
|
-
frame: Attr[AllowedSkyCoordFrames] = "
|
|
344
|
+
frame: Attr[AllowedSkyCoordFrames] = "icrs"
|
|
345
345
|
"""
|
|
346
346
|
From fixvis docs: clean and the im tool ignore the reference frame claimed by the UVW column (it is often mislabelled
|
|
347
347
|
as ITRF when it is really FK5 (J2000)) and instead assume the (u, v, w)s are in the same frame as the phase tracking
|
|
@@ -518,7 +518,7 @@ AllowedSpectralCoordFrames = Literal[
|
|
|
518
518
|
# "LSRK" -> "lsrk",
|
|
519
519
|
# "LSRD" -> "lsrd",
|
|
520
520
|
"BARY",
|
|
521
|
-
"GEO",
|
|
521
|
+
# "GEO", -> "gcrs"
|
|
522
522
|
"TOPO",
|
|
523
523
|
# astropy frames
|
|
524
524
|
"gcrs",
|
|
@@ -540,17 +540,20 @@ class SpectralCoordArray:
|
|
|
540
540
|
|
|
541
541
|
units: Attr[UnitsHertz] = ("Hz",)
|
|
542
542
|
|
|
543
|
-
observer: Attr[AllowedSpectralCoordFrames] = "
|
|
543
|
+
observer: Attr[AllowedSpectralCoordFrames] = "icrs"
|
|
544
544
|
"""
|
|
545
545
|
Capitalized reference observers are from casacore. TOPO implies creating astropy earth_location.
|
|
546
546
|
Astropy velocity reference frames are lowercase. Note that Astropy does not use the name 'TOPO' (telescope centric)
|
|
547
547
|
rather it assumes if no velocity frame is given that this is the default.
|
|
548
|
+
|
|
549
|
+
When converting from MSv2 and casacore frequency frames, the following translations from casacore to astropy
|
|
550
|
+
frame names are applied: GEO=>gcrs, LSRK=>lsrk, LSRD=>lsrd
|
|
548
551
|
"""
|
|
549
552
|
|
|
550
553
|
type: Attr[SpectralCoord] = "spectral_coord"
|
|
551
554
|
|
|
552
555
|
|
|
553
|
-
AllowedLocationFrames = Literal["
|
|
556
|
+
AllowedLocationFrames = Literal["ITRS", "Undefined"]
|
|
554
557
|
|
|
555
558
|
|
|
556
559
|
AllowedLocationCoordinateSystems = Literal[
|
|
@@ -562,11 +565,16 @@ AllowedLocationCoordinateSystems = Literal[
|
|
|
562
565
|
]
|
|
563
566
|
|
|
564
567
|
|
|
568
|
+
AllowedEllipsoid = Literal["GRS80", "WGS84", "WGS72"]
|
|
569
|
+
|
|
570
|
+
|
|
565
571
|
@xarray_dataarray_schema
|
|
566
572
|
class LocationArray:
|
|
567
573
|
"""
|
|
568
|
-
Measure type used for example in antenna_xds/ANTENNA_POSITION,
|
|
569
|
-
|
|
574
|
+
Measure type used for example in antenna_xds/ANTENNA_POSITION, weather_xds/STATION_POSITION,
|
|
575
|
+
field_and_source_xds(ephemeris)/OBSERVER_POSITION.
|
|
576
|
+
|
|
577
|
+
Data dimensions can be CartesianPosLabel or EllipsoidPosLabel
|
|
570
578
|
"""
|
|
571
579
|
|
|
572
580
|
data: Data[Union[EllipsoidPosLabel, CartesianPosLabel], float]
|
|
@@ -575,13 +583,13 @@ class LocationArray:
|
|
|
575
583
|
"""
|
|
576
584
|
If the units are a list of strings then it must be the same length as
|
|
577
585
|
the last dimension of the data array. This allows for having different
|
|
578
|
-
units in the same data array,for example geodetic coordinates could use
|
|
586
|
+
units in the same data array, for example geodetic coordinates could use
|
|
579
587
|
``['rad','rad','m']``.
|
|
580
588
|
"""
|
|
581
589
|
|
|
582
590
|
frame: Attr[AllowedLocationFrames]
|
|
583
591
|
"""
|
|
584
|
-
Can be
|
|
592
|
+
Reference frame. Can be ITRS (assumed for all Earth locations) or Undefined (used in non-Earth locations).
|
|
585
593
|
"""
|
|
586
594
|
|
|
587
595
|
coordinate_system: Attr[AllowedLocationCoordinateSystems]
|
|
@@ -589,24 +597,29 @@ class LocationArray:
|
|
|
589
597
|
|
|
590
598
|
origin_object_name: Attr[str]
|
|
591
599
|
"""
|
|
592
|
-
earth/sun/moon/etc
|
|
600
|
+
earth/sun/moon/etc.
|
|
601
|
+
"""
|
|
602
|
+
|
|
603
|
+
ellipsoid: Optional[Attr[AllowedEllipsoid]]
|
|
604
|
+
"""
|
|
605
|
+
Ellipsoid used in geodetic Earth locations (with EllipsoidPosLabel coordinate)
|
|
593
606
|
"""
|
|
594
607
|
|
|
595
608
|
type: Attr[Location] = "location"
|
|
596
|
-
""" """
|
|
609
|
+
""" Measure type. Should be ``"location"``."""
|
|
597
610
|
|
|
598
611
|
|
|
599
612
|
@xarray_dataarray_schema
|
|
600
613
|
class EllipsoidPosLocationArray:
|
|
601
614
|
"""
|
|
602
|
-
Measure type used for example in field_and_source_xds/
|
|
615
|
+
Measure type used for example in field_and_source_xds(ephemeris) / SUB_OBSERVER_DIRECTION, SUB_SOLAR_POSITION
|
|
603
616
|
"""
|
|
604
617
|
|
|
605
618
|
data: Data[EllipsoidPosLabel, float]
|
|
606
619
|
|
|
607
620
|
frame: Attr[AllowedLocationFrames]
|
|
608
621
|
"""
|
|
609
|
-
Can be
|
|
622
|
+
Reference frame. Can be ITRS (assumed for all Earth locations) or Undefined (used in non-Earth locations).
|
|
610
623
|
"""
|
|
611
624
|
|
|
612
625
|
coordinate_system: Attr[AllowedLocationCoordinateSystems]
|
|
@@ -618,7 +631,7 @@ class EllipsoidPosLocationArray:
|
|
|
618
631
|
"""
|
|
619
632
|
|
|
620
633
|
type: Attr[Location] = "location"
|
|
621
|
-
""" """
|
|
634
|
+
""" Measure type. Should be ``"location"``."""
|
|
622
635
|
|
|
623
636
|
units: Attr[UnitsOfPositionInRadians] = ("rad", "rad", "m")
|
|
624
637
|
"""
|
|
@@ -1445,7 +1458,7 @@ class AntennaXds:
|
|
|
1445
1458
|
# Coordinates
|
|
1446
1459
|
antenna_name: Coordof[AntennaNameArray]
|
|
1447
1460
|
""" Antenna name """
|
|
1448
|
-
|
|
1461
|
+
station_name: Coord[AntennaName, str]
|
|
1449
1462
|
""" Name of the station pad (relevant to arrays with moving antennas). """
|
|
1450
1463
|
mount: Coord[AntennaName, str]
|
|
1451
1464
|
""" Mount type of the antenna. Reserved keywords include: ”EQUATORIAL” - equatorial mount;
|
|
@@ -1529,7 +1542,7 @@ class GainCurveXds:
|
|
|
1529
1542
|
# Coordinates
|
|
1530
1543
|
antenna_name: Coordof[AntennaNameArray]
|
|
1531
1544
|
""" Antenna name """
|
|
1532
|
-
|
|
1545
|
+
station_name: Coord[AntennaName, str]
|
|
1533
1546
|
""" Name of the station pad (relevant to arrays with moving antennas). """
|
|
1534
1547
|
mount: Coord[AntennaName, str]
|
|
1535
1548
|
""" Mount type of the antenna. Reserved keywords include: ”EQUATORIAL” - equatorial mount;
|
|
@@ -1588,7 +1601,7 @@ class PhaseCalibrationXds:
|
|
|
1588
1601
|
# Coordinates
|
|
1589
1602
|
antenna_name: Coordof[AntennaNameArray]
|
|
1590
1603
|
""" Antenna name """
|
|
1591
|
-
|
|
1604
|
+
station_name: Coord[AntennaName, str]
|
|
1592
1605
|
""" Name of the station pad (relevant to arrays with moving antennas). """
|
|
1593
1606
|
mount: Coord[AntennaName, str]
|
|
1594
1607
|
""" Mount type of the antenna. Reserved keywords include: ”EQUATORIAL” - equatorial mount;
|
|
@@ -1672,13 +1685,11 @@ class WeatherXds:
|
|
|
1672
1685
|
|
|
1673
1686
|
# Coordinates
|
|
1674
1687
|
station_name: Coord[StationName, str]
|
|
1675
|
-
""" Station
|
|
1688
|
+
""" Station name """
|
|
1676
1689
|
time: Optional[Coordof[TimeInterpolatedCoordArray]]
|
|
1677
1690
|
""" Mid-point of the time interval. Labeled 'time' when interpolated to main time axis """
|
|
1678
1691
|
time_weather: Optional[Coordof[TimeWeatherCoordArray]]
|
|
1679
1692
|
""" Mid-point of the time interval. Labeled 'time_weather' when not interpolated to main time axis """
|
|
1680
|
-
antenna_name: Optional[Coordof[AntennaNameArray]]
|
|
1681
|
-
""" Antenna identifier """
|
|
1682
1693
|
ellipsoid_pos_label: Optional[Coord[EllipsoidPosLabel, str]] = (
|
|
1683
1694
|
"lon",
|
|
1684
1695
|
"lat",
|
|
@@ -1688,6 +1699,10 @@ class WeatherXds:
|
|
|
1688
1699
|
cartesian_pos_label: Optional[Coord[CartesianPosLabel, str]] = ("x", "y", "z")
|
|
1689
1700
|
""" Coordinate labels of geocentric earth location data (typically shape 3 and 'x', 'y', 'z')"""
|
|
1690
1701
|
|
|
1702
|
+
# Station position variable - required
|
|
1703
|
+
STATION_POSITION: Data[tuple[StationName], LocationArray] = None
|
|
1704
|
+
""" Position of the weather station """
|
|
1705
|
+
|
|
1691
1706
|
# Data variables (all optional)
|
|
1692
1707
|
H2O: Optional[
|
|
1693
1708
|
Data[
|
|
@@ -1766,8 +1781,6 @@ class WeatherXds:
|
|
|
1766
1781
|
]
|
|
1767
1782
|
] = None
|
|
1768
1783
|
""" Average wind speed """
|
|
1769
|
-
STATION_POSITION: Optional[Data[tuple[StationName], LocationArray]] = None
|
|
1770
|
-
""" Station position """
|
|
1771
1784
|
|
|
1772
1785
|
# Attributes
|
|
1773
1786
|
type: Attr[Literal["weather"]] = "weather"
|
|
@@ -1883,7 +1896,9 @@ class SystemCalibrationXds:
|
|
|
1883
1896
|
|
|
1884
1897
|
# Coordinates
|
|
1885
1898
|
antenna_name: Coordof[AntennaNameArray]
|
|
1886
|
-
""" Antenna
|
|
1899
|
+
""" Antenna name """
|
|
1900
|
+
station_name: Coord[AntennaName, str]
|
|
1901
|
+
""" Name of the station pad (relevant to arrays with moving antennas). """
|
|
1887
1902
|
receptor_label: Coord[ReceptorLabel, str]
|
|
1888
1903
|
""" Names of receptors """
|
|
1889
1904
|
polarization_type: Coord[tuple[AntennaName, ReceptorLabel], str]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xradio
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.51
|
|
4
4
|
Summary: Xarray Radio Astronomy Data IO
|
|
5
|
-
Author-email: Jan-Willem Steeb <jsteeb@nrao.edu>
|
|
5
|
+
Author-email: Jan-Willem Steeb <jsteeb@nrao.edu>, Federico Montesino Pouzols <pouzols@eso.edu>, Dave Mehringer <dmehring@nrao.edu>, Peter Wortmann <peter.wortmann@skao.int>
|
|
6
6
|
License: BSD 3-Clause License
|
|
7
7
|
|
|
8
8
|
All works in this repository are copyrighted 2024.
|
|
@@ -43,7 +43,7 @@ License-File: LICENSE.txt
|
|
|
43
43
|
Requires-Dist: astropy
|
|
44
44
|
Requires-Dist: dask
|
|
45
45
|
Requires-Dist: distributed
|
|
46
|
-
Requires-Dist: toolviper
|
|
46
|
+
Requires-Dist: toolviper>=0.0.11
|
|
47
47
|
Requires-Dist: numba>=0.57.0
|
|
48
48
|
Requires-Dist: numpy
|
|
49
49
|
Requires-Dist: pytest
|
|
@@ -79,7 +79,13 @@ Dynamic: license-file
|
|
|
79
79
|
# xradio
|
|
80
80
|
Xarray Radio Astronomy Data IO is still in development.
|
|
81
81
|
|
|
82
|
-
[](https://www.python.org/downloads/release/python-3130/)
|
|
83
|
+

|
|
84
|
+

|
|
85
|
+

|
|
86
|
+
[](https://codecov.io/gh/casangi/xradio/branch/main/xradio)
|
|
87
|
+
[](https://xradio.readthedocs.io)
|
|
88
|
+
[](https://pypi.python.org/pypi/xradio/)
|
|
83
89
|
|
|
84
90
|
# Installing
|
|
85
91
|
It is recommended to use the conda environment manager from [miniforge](https://github.com/conda-forge/miniforge) to create a clean, self-contained runtime where XRADIO and all its dependencies can be installed:
|
xradio-0.0.50/README.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# xradio
|
|
2
|
-
Xarray Radio Astronomy Data IO is still in development.
|
|
3
|
-
|
|
4
|
-
[](https://www.python.org/downloads/release/python-380/)
|
|
5
|
-
|
|
6
|
-
# Installing
|
|
7
|
-
It is recommended to use the conda environment manager from [miniforge](https://github.com/conda-forge/miniforge) to create a clean, self-contained runtime where XRADIO and all its dependencies can be installed:
|
|
8
|
-
```sh
|
|
9
|
-
conda create --name xradio python=3.12 --no-default-packages
|
|
10
|
-
conda activate xradio
|
|
11
|
-
```
|
|
12
|
-
> 📝 On macOS it is required to pre-install `python-casacore` using `conda install -c conda-forge python-casacore`.
|
|
13
|
-
|
|
14
|
-
XRADIO can now be installed using:
|
|
15
|
-
```sh
|
|
16
|
-
pip install xradio
|
|
17
|
-
```
|
|
18
|
-
This will also install the minimal dependencies for XRADIO. To install the minimal dependencies and the interactive components (JupyterLab) use:
|
|
19
|
-
```sh
|
|
20
|
-
pip install "xradio[interactive]"
|
|
21
|
-
```
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py
RENAMED
|
File without changes
|
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py
RENAMED
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py
RENAMED
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/table_query.py
RENAMED
|
File without changes
|
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py
RENAMED
|
File without changes
|
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/optimised_functions.py
RENAMED
|
File without changes
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/partition_queries.py
RENAMED
|
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
|
{xradio-0.0.50 → xradio-0.0.51}/src/xradio/measurement_set/convert_msv2_to_processing_set.py
RENAMED
|
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
|