xradio 0.0.49__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.49/src/xradio.egg-info → xradio-0.0.51}/PKG-INFO +11 -4
- xradio-0.0.51/README.md +27 -0
- {xradio-0.0.49 → xradio-0.0.51}/pyproject.toml +7 -3
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/schema.py +2 -2
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/conversion.py +5 -4
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/create_antenna_xds.py +5 -5
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py +2 -1
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +151 -13
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/measurement_set_xdt.py +126 -4
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/processing_set_xdt.py +151 -36
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/schema.py +42 -25
- {xradio-0.0.49 → xradio-0.0.51/src/xradio.egg-info}/PKG-INFO +11 -4
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio.egg-info/requires.txt +2 -1
- xradio-0.0.49/README.md +0 -21
- {xradio-0.0.49 → xradio-0.0.51}/LICENSE.txt +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/MANIFEST.in +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/setup.cfg +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/_casacore/tables.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/coord_math.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/dict_helpers.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/list_and_array.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/zarr/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/_utils/zarr/common.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_casacore/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_casacore/common.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_casacore/xds_from_casacore.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_casacore/xds_to_casacore.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_fits/xds_from_fits.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_zarr/common.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_zarr/xds_from_zarr.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_zarr/xds_to_zarr.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/_zarr/zarr_low_level.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/casacore.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/common.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/fits.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/image_factory.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/_util/zarr.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/image/image.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/load.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/table_query.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/write.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/chunks.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/descr.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv2_msv3.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/optimised_functions.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/partition_queries.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/partitions.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_msv2/subtables.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/cds.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/partition_attrs.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/stokes_types.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_utils/xds_helper.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_zarr/encoding.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_zarr/read.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/_zarr/write.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/msv2.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/_utils/zarr.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/convert_msv2_to_processing_set.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/load_processing_set.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/measurement_set/open_processing_set.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/schema/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/schema/bases.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/schema/check.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/schema/dataclass.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/schema/metamodel.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/schema/typing.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/sphinx/__init__.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio/sphinx/schema_table.py +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio.egg-info/SOURCES.txt +0 -0
- {xradio-0.0.49 → xradio-0.0.51}/src/xradio.egg-info/dependency_links.txt +0 -0
- {xradio-0.0.49 → 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
|
|
@@ -56,6 +56,7 @@ Requires-Dist: zarr<3,>=2
|
|
|
56
56
|
Requires-Dist: pyarrow
|
|
57
57
|
Requires-Dist: python_casacore>=3.6.1; sys_platform != "darwin"
|
|
58
58
|
Requires-Dist: typeguard
|
|
59
|
+
Requires-Dist: numcodecs<0.16
|
|
59
60
|
Provides-Extra: interactive
|
|
60
61
|
Requires-Dist: matplotlib; extra == "interactive"
|
|
61
62
|
Requires-Dist: prettytable; extra == "interactive"
|
|
@@ -78,7 +79,13 @@ Dynamic: license-file
|
|
|
78
79
|
# xradio
|
|
79
80
|
Xarray Radio Astronomy Data IO is still in development.
|
|
80
81
|
|
|
81
|
-
[](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/)
|
|
82
89
|
|
|
83
90
|
# Installing
|
|
84
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',
|
|
@@ -25,7 +28,8 @@ dependencies = [
|
|
|
25
28
|
'zarr>=2,<3',
|
|
26
29
|
'pyarrow',
|
|
27
30
|
'python_casacore>=3.6.1; sys_platform != "darwin" ',
|
|
28
|
-
'typeguard'
|
|
31
|
+
'typeguard',
|
|
32
|
+
'numcodecs<0.16'
|
|
29
33
|
]
|
|
30
34
|
|
|
31
35
|
[project.optional-dependencies]
|
|
@@ -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
|
|
@@ -1341,7 +1341,7 @@ def convert_and_write_partition(
|
|
|
1341
1341
|
|
|
1342
1342
|
ms_xdt["/antenna_xds"] = ant_xds
|
|
1343
1343
|
for group_name in xds.attrs["data_groups"]:
|
|
1344
|
-
ms_xdt["/" + f"
|
|
1344
|
+
ms_xdt["/" + f"field_and_source_{group_name}_xds"] = field_and_source_xds
|
|
1345
1345
|
|
|
1346
1346
|
if with_pointing and len(pointing_xds.data_vars) > 0:
|
|
1347
1347
|
ms_xdt["/pointing_xds"] = 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)
|
|
@@ -1468,6 +1468,7 @@ def add_group_to_data_groups(
|
|
|
1468
1468
|
"correlated_data": correlated_data_name,
|
|
1469
1469
|
"flag": "FLAG",
|
|
1470
1470
|
"weight": "WEIGHT",
|
|
1471
|
+
"field_and_source": f"field_and_source_{what_group}_xds",
|
|
1471
1472
|
"description": f"Data group derived from the data column '{correlated_data_name}' of an MSv2 converted to MSv4",
|
|
1472
1473
|
"date": datetime.datetime.now(datetime.timezone.utc).isoformat(),
|
|
1473
1474
|
}
|
{xradio-0.0.49 → 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
|
|
@@ -93,17 +93,34 @@ class MeasurementSetXdt:
|
|
|
93
93
|
if data_group_name is not None:
|
|
94
94
|
sel_data_group_set = set(
|
|
95
95
|
self._xdt.attrs["data_groups"][data_group_name].values()
|
|
96
|
-
)
|
|
96
|
+
) - set(["date", "description"])
|
|
97
|
+
|
|
98
|
+
sel_field_and_source_xds = self._xdt.attrs["data_groups"][data_group_name][
|
|
99
|
+
"field_and_source"
|
|
100
|
+
]
|
|
97
101
|
|
|
98
102
|
data_variables_to_drop = []
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
field_and_source_to_drop = []
|
|
104
|
+
for dg_name, dg in self._xdt.attrs["data_groups"].items():
|
|
105
|
+
print(f"Data group: {dg_name}", dg)
|
|
106
|
+
f_and_s = dg["field_and_source"]
|
|
107
|
+
dg_copy = dg.copy()
|
|
108
|
+
dg_copy.pop("date", None)
|
|
109
|
+
dg_copy.pop("description", None)
|
|
110
|
+
dg_copy.pop("field_and_source", None)
|
|
111
|
+
temp_set = set(dg_copy.values()) - sel_data_group_set
|
|
101
112
|
data_variables_to_drop.extend(list(temp_set))
|
|
102
113
|
|
|
114
|
+
if f_and_s != sel_field_and_source_xds:
|
|
115
|
+
field_and_source_to_drop.append(f_and_s)
|
|
116
|
+
|
|
103
117
|
data_variables_to_drop = list(set(data_variables_to_drop))
|
|
104
118
|
|
|
105
119
|
sel_ms_xdt = self._xdt
|
|
106
120
|
|
|
121
|
+
print("Data variables to drop: ", data_variables_to_drop)
|
|
122
|
+
print("Field and source to drop: ", field_and_source_to_drop)
|
|
123
|
+
|
|
107
124
|
sel_corr_xds = self._xdt.ds.sel(
|
|
108
125
|
indexers, method, tolerance, drop, **indexers_kwargs
|
|
109
126
|
).drop_vars(data_variables_to_drop)
|
|
@@ -140,7 +157,10 @@ class MeasurementSetXdt:
|
|
|
140
157
|
else:
|
|
141
158
|
data_group_name = list(self._xdt.attrs["data_groups"].keys())[0]
|
|
142
159
|
|
|
143
|
-
|
|
160
|
+
field_and_source_xds_name = self._xdt.attrs["data_groups"][data_group_name][
|
|
161
|
+
"field_and_source"
|
|
162
|
+
]
|
|
163
|
+
return self._xdt[field_and_source_xds_name].ds
|
|
144
164
|
|
|
145
165
|
def get_partition_info(self, data_group_name: str = None) -> dict:
|
|
146
166
|
"""
|
|
@@ -195,3 +215,105 @@ class MeasurementSetXdt:
|
|
|
195
215
|
}
|
|
196
216
|
|
|
197
217
|
return partition_info
|
|
218
|
+
|
|
219
|
+
def add_data_group(
|
|
220
|
+
self,
|
|
221
|
+
new_data_group_name: str,
|
|
222
|
+
correlated_data: str = None,
|
|
223
|
+
weight: str = None,
|
|
224
|
+
flag: str = None,
|
|
225
|
+
uvw: str = None,
|
|
226
|
+
field_and_source_xds: str = None,
|
|
227
|
+
date_time: str = None,
|
|
228
|
+
description: str = None,
|
|
229
|
+
data_group_dv_shared_with: str = None,
|
|
230
|
+
) -> xr.DataTree:
|
|
231
|
+
"""_summary_
|
|
232
|
+
|
|
233
|
+
Parameters
|
|
234
|
+
----------
|
|
235
|
+
new_data_group_name : str
|
|
236
|
+
_description_
|
|
237
|
+
correlated_data : str, optional
|
|
238
|
+
_description_, by default None
|
|
239
|
+
weights : str, optional
|
|
240
|
+
_description_, by default None
|
|
241
|
+
flag : str, optional
|
|
242
|
+
_description_, by default None
|
|
243
|
+
uvw : str, optional
|
|
244
|
+
_description_, by default None
|
|
245
|
+
field_and_source_xds : str, optional
|
|
246
|
+
_description_, by default None
|
|
247
|
+
date_time : str, optional
|
|
248
|
+
_description_, by default None
|
|
249
|
+
description : str, optional
|
|
250
|
+
_description_, by default None
|
|
251
|
+
data_group_dv_shared_with : str, optional
|
|
252
|
+
_description_, by default "base"
|
|
253
|
+
|
|
254
|
+
Returns
|
|
255
|
+
-------
|
|
256
|
+
xr.DataTree
|
|
257
|
+
_description_
|
|
258
|
+
"""
|
|
259
|
+
|
|
260
|
+
if data_group_dv_shared_with is None:
|
|
261
|
+
data_group_dv_shared_with = self._xdt.xr_ms._get_default_data_group_name()
|
|
262
|
+
default_data_group = self._xdt.attrs["data_groups"][data_group_dv_shared_with]
|
|
263
|
+
|
|
264
|
+
new_data_group = {}
|
|
265
|
+
|
|
266
|
+
if correlated_data is None:
|
|
267
|
+
correlated_data = default_data_group["correlated_data"]
|
|
268
|
+
new_data_group["correlated_data"] = correlated_data
|
|
269
|
+
assert (
|
|
270
|
+
correlated_data in self._xdt.ds.data_vars
|
|
271
|
+
), f"Data variable {correlated_data} not found in dataset."
|
|
272
|
+
|
|
273
|
+
if weight is None:
|
|
274
|
+
weight = default_data_group["weight"]
|
|
275
|
+
new_data_group["weight"] = weight
|
|
276
|
+
assert (
|
|
277
|
+
weight in self._xdt.ds.data_vars
|
|
278
|
+
), f"Data variable {weight} not found in dataset."
|
|
279
|
+
|
|
280
|
+
if flag is None:
|
|
281
|
+
flag = default_data_group["flag"]
|
|
282
|
+
new_data_group["flag"] = flag
|
|
283
|
+
assert (
|
|
284
|
+
flag in self._xdt.ds.data_vars
|
|
285
|
+
), f"Data variable {flag} not found in dataset."
|
|
286
|
+
|
|
287
|
+
if self._xdt.attrs["type"] == "visibility":
|
|
288
|
+
if uvw is None:
|
|
289
|
+
uvw = default_data_group["uvw"]
|
|
290
|
+
new_data_group["uvw"] = uvw
|
|
291
|
+
assert (
|
|
292
|
+
uvw in self._xdt.ds.data_vars
|
|
293
|
+
), f"Data variable {uvw} not found in dataset."
|
|
294
|
+
|
|
295
|
+
if field_and_source_xds is None:
|
|
296
|
+
field_and_source_xds = default_data_group["field_and_source_xds"]
|
|
297
|
+
new_data_group["field_and_source"] = field_and_source_xds
|
|
298
|
+
assert (
|
|
299
|
+
field_and_source_xds in self._xdt.children
|
|
300
|
+
), f"Data variable {field_and_source_xds} not found in dataset."
|
|
301
|
+
|
|
302
|
+
if date_time is None:
|
|
303
|
+
date_time = datetime.now().isoformat()
|
|
304
|
+
new_data_group["date"] = date_time
|
|
305
|
+
|
|
306
|
+
if description is None:
|
|
307
|
+
description = ""
|
|
308
|
+
new_data_group["description"] = description
|
|
309
|
+
|
|
310
|
+
self._xdt.attrs["data_groups"][new_data_group_name] = new_data_group
|
|
311
|
+
|
|
312
|
+
return self._xdt
|
|
313
|
+
|
|
314
|
+
def _get_default_data_group_name(self):
|
|
315
|
+
if "base" in self._xdt.attrs["data_groups"].keys():
|
|
316
|
+
data_group_name = "base"
|
|
317
|
+
else:
|
|
318
|
+
data_group_name = list(self._xdt.attrs["data_groups"].keys())[0]
|
|
319
|
+
return data_group_name
|