xradio 0.0.48__py3-none-any.whl → 0.0.50__py3-none-any.whl
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/__init__.py +1 -0
- xradio/_utils/dict_helpers.py +69 -2
- xradio/image/_util/__init__.py +0 -3
- xradio/image/_util/_casacore/common.py +0 -13
- xradio/image/_util/_casacore/xds_from_casacore.py +102 -97
- xradio/image/_util/_casacore/xds_to_casacore.py +36 -24
- xradio/image/_util/_fits/xds_from_fits.py +81 -36
- xradio/image/_util/_zarr/zarr_low_level.py +3 -3
- xradio/image/_util/casacore.py +7 -5
- xradio/image/_util/common.py +13 -26
- xradio/image/_util/image_factory.py +143 -191
- xradio/image/image.py +10 -59
- xradio/measurement_set/__init__.py +11 -6
- xradio/measurement_set/_utils/_msv2/_tables/read.py +187 -46
- xradio/measurement_set/_utils/_msv2/_tables/table_query.py +22 -0
- xradio/measurement_set/_utils/_msv2/conversion.py +352 -318
- xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +20 -17
- xradio/measurement_set/convert_msv2_to_processing_set.py +46 -6
- xradio/measurement_set/load_processing_set.py +100 -53
- xradio/measurement_set/measurement_set_xdt.py +319 -0
- xradio/measurement_set/open_processing_set.py +122 -86
- xradio/measurement_set/processing_set_xdt.py +1552 -0
- xradio/measurement_set/schema.py +201 -94
- xradio/schema/bases.py +5 -1
- xradio/schema/check.py +97 -5
- {xradio-0.0.48.dist-info → xradio-0.0.50.dist-info}/METADATA +5 -4
- {xradio-0.0.48.dist-info → xradio-0.0.50.dist-info}/RECORD +30 -30
- {xradio-0.0.48.dist-info → xradio-0.0.50.dist-info}/WHEEL +1 -1
- xradio/measurement_set/measurement_set_xds.py +0 -117
- xradio/measurement_set/processing_set.py +0 -803
- {xradio-0.0.48.dist-info → xradio-0.0.50.dist-info/licenses}/LICENSE.txt +0 -0
- {xradio-0.0.48.dist-info → xradio-0.0.50.dist-info}/top_level.txt +0 -0
xradio/measurement_set/schema.py
CHANGED
|
@@ -9,6 +9,8 @@ from xradio.schema.bases import (
|
|
|
9
9
|
from xradio.schema.typing import Attr, Coord, Coordof, Data, Dataof, Name
|
|
10
10
|
import numpy
|
|
11
11
|
|
|
12
|
+
MSV4_SCHEMA_VERSION = "4.0.-9988"
|
|
13
|
+
|
|
12
14
|
# Dimensions
|
|
13
15
|
Time = Literal["time"]
|
|
14
16
|
""" Observation time dimension """
|
|
@@ -670,7 +672,7 @@ class DopplerArray:
|
|
|
670
672
|
data: Data[ZD, numpy.float64]
|
|
671
673
|
|
|
672
674
|
type: Attr[Doppler] = "doppler"
|
|
673
|
-
""" Coordinate type. Should be ``"
|
|
675
|
+
""" Coordinate type. Should be ``"doppler"``. """
|
|
674
676
|
|
|
675
677
|
units: Attr[UnitsOfDopplerShift] = ("m/s",)
|
|
676
678
|
""" Units to associate with axis, [ratio]/[m/s]"""
|
|
@@ -788,11 +790,18 @@ class FlagArray:
|
|
|
788
790
|
flagged bad if the ``FLAG`` array element is ``True``.
|
|
789
791
|
"""
|
|
790
792
|
|
|
793
|
+
# data: Data[
|
|
794
|
+
# Union[
|
|
795
|
+
# tuple[Time, BaselineId, Frequency, Polarization],
|
|
796
|
+
# tuple[Time, BaselineId, Frequency],
|
|
797
|
+
# tuple[Time, BaselineId],
|
|
798
|
+
# tuple[Time, AntennaName, Frequency, Polarization], # SD
|
|
799
|
+
# ],
|
|
800
|
+
# bool,
|
|
801
|
+
# ]
|
|
791
802
|
data: Data[
|
|
792
803
|
Union[
|
|
793
804
|
tuple[Time, BaselineId, Frequency, Polarization],
|
|
794
|
-
tuple[Time, BaselineId, Frequency],
|
|
795
|
-
tuple[Time, BaselineId],
|
|
796
805
|
tuple[Time, AntennaName, Frequency, Polarization], # SD
|
|
797
806
|
],
|
|
798
807
|
bool,
|
|
@@ -820,12 +829,20 @@ class WeightArray:
|
|
|
820
829
|
data: Data[
|
|
821
830
|
Union[
|
|
822
831
|
tuple[Time, BaselineId, Frequency, Polarization],
|
|
823
|
-
tuple[Time, BaselineId, Frequency],
|
|
824
|
-
tuple[Time, BaselineId],
|
|
825
832
|
tuple[Time, AntennaName, Frequency, Polarization], # SD
|
|
826
833
|
],
|
|
827
834
|
Union[numpy.float16, numpy.float32, numpy.float64],
|
|
828
835
|
]
|
|
836
|
+
|
|
837
|
+
# data: Data[
|
|
838
|
+
# Union[
|
|
839
|
+
# tuple[Time, BaselineId, Frequency, Polarization],
|
|
840
|
+
# tuple[Time, BaselineId, Frequency],
|
|
841
|
+
# tuple[Time, BaselineId],
|
|
842
|
+
# tuple[Time, AntennaName, Frequency, Polarization], # SD
|
|
843
|
+
# ],
|
|
844
|
+
# Union[numpy.float16, numpy.float32, numpy.float64],
|
|
845
|
+
# ]
|
|
829
846
|
"""Visibility weights"""
|
|
830
847
|
time: Coordof[TimeCoordArray]
|
|
831
848
|
baseline_id: Optional[Coordof[BaselineArray]] # Only IF
|
|
@@ -928,19 +945,79 @@ class TimeSamplingArray:
|
|
|
928
945
|
units: Attr[UnitsSeconds] = ("s",)
|
|
929
946
|
|
|
930
947
|
|
|
948
|
+
# @xarray_dataarray_schema
|
|
949
|
+
# class FreqSamplingArray:
|
|
950
|
+
# """
|
|
951
|
+
# Model of frequency related data variables of the main dataset, such as EFFECTIV_CHANNEL_WIDTH and FREQUENCY_CENTROID.
|
|
952
|
+
# """
|
|
953
|
+
|
|
954
|
+
# data: Data[
|
|
955
|
+
# Union[
|
|
956
|
+
# tuple[Time, BaselineId, Frequency, Polarization],
|
|
957
|
+
# tuple[Time, BaselineId, Frequency],
|
|
958
|
+
# tuple[Time, Frequency],
|
|
959
|
+
# tuple[Frequency],
|
|
960
|
+
# ],
|
|
961
|
+
# float,
|
|
962
|
+
# ]
|
|
963
|
+
# """
|
|
964
|
+
# Data about frequency sampling, such as centroid or integration
|
|
965
|
+
# time. Concrete function depends on concrete data array within
|
|
966
|
+
# :py:class:`VisibilityXds` or :py:class:`SpectrumXds`.
|
|
967
|
+
# """
|
|
968
|
+
# frequency: Coordof[FrequencyArray]
|
|
969
|
+
# time: Optional[Coordof[TimeCoordArray]] = None
|
|
970
|
+
# baseline_id: Optional[Coordof[BaselineArray]] = None
|
|
971
|
+
# polarization: Optional[Coordof[PolarizationArray]] = None
|
|
972
|
+
# long_name: Optional[Attr[str]] = "Frequency sampling data"
|
|
973
|
+
# units: Attr[UnitsHertz] = ("Hz",)
|
|
974
|
+
# observer: Attr[AllowedSpectralCoordFrames] = "icrs"
|
|
975
|
+
# """
|
|
976
|
+
# Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
|
|
977
|
+
# Note that Astropy does not use the name
|
|
978
|
+
# 'topo' (telescope centric) velocity frame, rather it assumes if no velocity
|
|
979
|
+
# frame is given that this is the default.
|
|
980
|
+
# """
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
@xarray_dataarray_schema
|
|
984
|
+
class FrequencyCentroidArray:
|
|
985
|
+
"""
|
|
986
|
+
Model of frequency related data variables of the main dataset, such as FREQUENCY_CENTROID.
|
|
987
|
+
"""
|
|
988
|
+
|
|
989
|
+
data: Data[
|
|
990
|
+
tuple[Frequency],
|
|
991
|
+
float,
|
|
992
|
+
]
|
|
993
|
+
"""
|
|
994
|
+
Data about frequency sampling, such as centroid or integration
|
|
995
|
+
time. Concrete function depends on concrete data array within
|
|
996
|
+
:py:class:`VisibilityXds` or :py:class:`SpectrumXds`.
|
|
997
|
+
"""
|
|
998
|
+
frequency: Coordof[FrequencyArray]
|
|
999
|
+
long_name: Optional[Attr[str]] = "Frequency sampling data"
|
|
1000
|
+
units: Attr[UnitsHertz] = ("Hz",)
|
|
1001
|
+
observer: Attr[AllowedSpectralCoordFrames] = "icrs"
|
|
1002
|
+
"""
|
|
1003
|
+
Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
|
|
1004
|
+
Note that Astropy does not use the name
|
|
1005
|
+
'topo' (telescope centric) velocity frame, rather it assumes if no velocity
|
|
1006
|
+
frame is given that this is the default.
|
|
1007
|
+
"""
|
|
1008
|
+
|
|
1009
|
+
|
|
931
1010
|
@xarray_dataarray_schema
|
|
932
|
-
class
|
|
1011
|
+
class EffectiveChannelWidthArray:
|
|
933
1012
|
"""
|
|
934
|
-
Model of frequency related data variables of the main dataset, such as EFFECTIV_CHANNEL_WIDTH
|
|
1013
|
+
Model of frequency related data variables of the main dataset, such as EFFECTIV_CHANNEL_WIDTH.
|
|
935
1014
|
"""
|
|
936
1015
|
|
|
937
1016
|
data: Data[
|
|
938
1017
|
Union[
|
|
939
1018
|
tuple[Time, BaselineId, Frequency, Polarization],
|
|
940
|
-
tuple[Time,
|
|
941
|
-
|
|
942
|
-
tuple[Frequency],
|
|
943
|
-
],
|
|
1019
|
+
tuple[Time, AntennaName, Frequency, Polarization],
|
|
1020
|
+
], # SD
|
|
944
1021
|
float,
|
|
945
1022
|
]
|
|
946
1023
|
"""
|
|
@@ -963,7 +1040,7 @@ class FreqSamplingArray:
|
|
|
963
1040
|
"""
|
|
964
1041
|
|
|
965
1042
|
|
|
966
|
-
# Define
|
|
1043
|
+
# Define FieldSourceXds and FieldSourceEphemerisXds already here, as they are needed in the
|
|
967
1044
|
# definition of VisibilityArray
|
|
968
1045
|
@xarray_dataset_schema
|
|
969
1046
|
class FieldSourceXds:
|
|
@@ -1222,9 +1299,6 @@ class SpectrumArray:
|
|
|
1222
1299
|
frequency: Coordof[FrequencyArray]
|
|
1223
1300
|
polarization: Coordof[PolarizationArray]
|
|
1224
1301
|
|
|
1225
|
-
field_and_source_xds: Attr[Union[FieldSourceXds, FieldSourceEphemerisXds]]
|
|
1226
|
-
""" Field and source information. Also alows for variant where ephemeris information is included. """
|
|
1227
|
-
|
|
1228
1302
|
long_name: Optional[Attr[str]] = "Spectrum values"
|
|
1229
1303
|
""" Long-form name to use for axis. Should be ``"Spectrum values"``"""
|
|
1230
1304
|
units: Attr[list[str]] = ("Jy",)
|
|
@@ -1244,9 +1318,6 @@ class VisibilityArray:
|
|
|
1244
1318
|
polarization: Coordof[PolarizationArray]
|
|
1245
1319
|
frequency: Coordof[FrequencyArray]
|
|
1246
1320
|
|
|
1247
|
-
field_and_source_xds: Attr[Union[FieldSourceXds, FieldSourceEphemerisXds]]
|
|
1248
|
-
""" Field and source information. Also alows for variant where ephemeris information is included. """
|
|
1249
|
-
|
|
1250
1321
|
long_name: Optional[Attr[str]] = "Visibility values"
|
|
1251
1322
|
""" Long-form name to use for axis. Should be ``"Visibility values"``"""
|
|
1252
1323
|
units: Attr[list[str]] = ("Jy",)
|
|
@@ -1257,32 +1328,32 @@ class VisibilityArray:
|
|
|
1257
1328
|
# Info dicts
|
|
1258
1329
|
|
|
1259
1330
|
|
|
1260
|
-
@dict_schema
|
|
1261
|
-
class PartitionInfoDict:
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1331
|
+
# @dict_schema
|
|
1332
|
+
# class PartitionInfoDict:
|
|
1333
|
+
# # spectral_window_id: missing / remove for good?
|
|
1334
|
+
# spectral_window_name: str
|
|
1335
|
+
# """ Spectral window Name """
|
|
1336
|
+
# # field_id: missing / probably remove for good?
|
|
1337
|
+
# field_name: list[str]
|
|
1338
|
+
# """ List of all field names """
|
|
1339
|
+
# polarization_setup: list[str]
|
|
1340
|
+
# """ List of polrization bases. """
|
|
1341
|
+
# scan_name: list[str]
|
|
1342
|
+
# """ List of scan names. """
|
|
1343
|
+
# source_name: list[str]
|
|
1344
|
+
# """ List of source names. """
|
|
1345
|
+
# # source_id: mising / remove for good?
|
|
1346
|
+
# intents: list[str]
|
|
1347
|
+
# """ An intent string identifies one intention of the scan, such as to calibrate or observe a
|
|
1348
|
+
# target. See :ref:`scan intents` for possible values. When converting from MSv2, the list of
|
|
1349
|
+
# intents is derived from the OBS_MODE column of MSv2 state table (every comma separated value
|
|
1350
|
+
# is taken as an intent). """
|
|
1351
|
+
# taql: Optional[str]
|
|
1352
|
+
# """ The taql query used if converted from MSv2. """
|
|
1353
|
+
# line_name: list[str]
|
|
1354
|
+
# """ Spectral line names """
|
|
1355
|
+
# antenna_name: Optional[str]
|
|
1356
|
+
# """ Name of antenna when partitioning also by antenna (single-dish). """
|
|
1286
1357
|
|
|
1287
1358
|
|
|
1288
1359
|
@dict_schema
|
|
@@ -1310,6 +1381,11 @@ class ObservationInfoDict:
|
|
|
1310
1381
|
"""ASDM: A reference to the Entity which contains the observing script."""
|
|
1311
1382
|
observing_log: Optional[str]
|
|
1312
1383
|
"""ASDM: Logs of the observation during this execu- tion block."""
|
|
1384
|
+
intents: list[str]
|
|
1385
|
+
""" An intent string identifies one intention of the scan, such as to calibrate or observe a
|
|
1386
|
+
target. See :ref:`scan intents` for possible values. When converting from MSv2, the list of
|
|
1387
|
+
intents is derived from the OBS_MODE column of MSv2 state table (every comma separated value
|
|
1388
|
+
is taken as an intent). """
|
|
1313
1389
|
|
|
1314
1390
|
|
|
1315
1391
|
@dict_schema
|
|
@@ -1322,6 +1398,41 @@ class ProcessorInfoDict:
|
|
|
1322
1398
|
"""Processor sub-type, e.g. ”GBT” or ”JIVE”."""
|
|
1323
1399
|
|
|
1324
1400
|
|
|
1401
|
+
@dict_schema
|
|
1402
|
+
class DataGroupDict:
|
|
1403
|
+
"""Defines a group of correlated data + flag + weight + uvw variables."""
|
|
1404
|
+
|
|
1405
|
+
correlated_data: str
|
|
1406
|
+
""" Name of the correlated data variable, for example 'VISIBILITY' or 'VISIBILITY_MODEL'. """
|
|
1407
|
+
flag: str
|
|
1408
|
+
""" Name of the flag variable, for example 'FLAG'. """
|
|
1409
|
+
weight: str
|
|
1410
|
+
""" Name of the weight variable of the group, for example 'WEIGHT'. """
|
|
1411
|
+
uvw: Optional[str]
|
|
1412
|
+
""" Name of the UVW variable of the group, for example 'UVW'. """
|
|
1413
|
+
field_and_source: str
|
|
1414
|
+
""" Name of the field_and_source_xds, for example field_and_source_xds_base. """
|
|
1415
|
+
description: str
|
|
1416
|
+
""" More details about the data group. """
|
|
1417
|
+
date: str
|
|
1418
|
+
""" Creation date-time, in ISO 8601 format: 'YYYY-MM-DDTHH:mm:ss.SSS'. """
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
@dict_schema
|
|
1422
|
+
class DataGroupsDict:
|
|
1423
|
+
"""Dictionary of data group dictionaries."""
|
|
1424
|
+
|
|
1425
|
+
base: DataGroupDict
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
@dict_schema
|
|
1429
|
+
class CreatorDict:
|
|
1430
|
+
software_name: str
|
|
1431
|
+
""" Software that created the Measurement Set (XRadio, etc.). """
|
|
1432
|
+
version: str
|
|
1433
|
+
""" Version of the software. """
|
|
1434
|
+
|
|
1435
|
+
|
|
1325
1436
|
# Data Sets
|
|
1326
1437
|
|
|
1327
1438
|
|
|
@@ -1338,11 +1449,13 @@ class AntennaXds:
|
|
|
1338
1449
|
""" Name of the station pad (relevant to arrays with moving antennas). """
|
|
1339
1450
|
mount: Coord[AntennaName, str]
|
|
1340
1451
|
""" Mount type of the antenna. Reserved keywords include: ”EQUATORIAL” - equatorial mount;
|
|
1341
|
-
”ALT-AZ
|
|
1342
|
-
"ALT-AZ+ROTATOR"
|
|
1452
|
+
”ALT-AZ”: azimuth-elevation mount;
|
|
1453
|
+
"ALT-AZ+ROTATOR": alt-az mount with feed rotator; introduced for ASKAP dishes;
|
|
1343
1454
|
"ALT-AZ+NASMYTH-R": Nasmyth mount with receivers at the right-hand side of the cabin. Many high-frequency antennas used for VLBI have such a mount typel;
|
|
1344
|
-
"ALT-AZ+NASMYTH-L
|
|
1345
|
-
|
|
1455
|
+
"ALT-AZ+NASMYTH-L": Nasmyth mount with receivers at the left-hand side of the cabin.
|
|
1456
|
+
"ALT-AZ+BWG-R": alt-az mount that uses a Beam Wave Guide to bring the focus down to the pedestal. The receivers are at the right-hand side of the cabin (-R). Compared to the Nasmyth mounts there is an extra correction term because there are now two rotating mirrors. See https://arxiv.org/abs/2210.13381 for more details.
|
|
1457
|
+
"ALT-AZ+BWG-L": alt-az mount that uses a Beam Wave Guide, as above, but with receivers at the left-hand side of the cabin.
|
|
1458
|
+
”X-Y”: x-y mount;
|
|
1346
1459
|
”SPACE-HALCA” - specific orientation model."""
|
|
1347
1460
|
telescope_name: Coord[AntennaName, str]
|
|
1348
1461
|
""" Useful when data is combined from mutiple arrays for example ACA + ALMA. """
|
|
@@ -1420,11 +1533,13 @@ class GainCurveXds:
|
|
|
1420
1533
|
""" Name of the station pad (relevant to arrays with moving antennas). """
|
|
1421
1534
|
mount: Coord[AntennaName, str]
|
|
1422
1535
|
""" Mount type of the antenna. Reserved keywords include: ”EQUATORIAL” - equatorial mount;
|
|
1423
|
-
”ALT-AZ
|
|
1424
|
-
"ALT-AZ+ROTATOR"
|
|
1536
|
+
”ALT-AZ”: azimuth-elevation mount;
|
|
1537
|
+
"ALT-AZ+ROTATOR": alt-az mount with feed rotator; introduced for ASKAP dishes;
|
|
1425
1538
|
"ALT-AZ+NASMYTH-R": Nasmyth mount with receivers at the right-hand side of the cabin. Many high-frequency antennas used for VLBI have such a mount typel;
|
|
1426
|
-
"ALT-AZ+NASMYTH-L
|
|
1427
|
-
|
|
1539
|
+
"ALT-AZ+NASMYTH-L": Nasmyth mount with receivers at the left-hand side of the cabin.
|
|
1540
|
+
"ALT-AZ+BWG-R": alt-az mount that uses a Beam Wave Guide to bring the focus down to the pedestal. The receivers are at the right-hand side of the cabin (-R). Compared to the Nasmyth mounts there is an extra correction term because there are now two rotating mirrors. See https://arxiv.org/abs/2210.13381 for more details.
|
|
1541
|
+
"ALT-AZ+BWG-L": alt-az mount that uses a Beam Wave Guide, as above, but with receivers at the left-hand side of the cabin.
|
|
1542
|
+
”X-Y”: x-y mount;
|
|
1428
1543
|
”SPACE-HALCA” - specific orientation model."""
|
|
1429
1544
|
telescope_name: Coord[AntennaName, str]
|
|
1430
1545
|
""" Useful when data is combined from mutiple arrays for example ACA + ALMA. """
|
|
@@ -1477,12 +1592,14 @@ class PhaseCalibrationXds:
|
|
|
1477
1592
|
""" Name of the station pad (relevant to arrays with moving antennas). """
|
|
1478
1593
|
mount: Coord[AntennaName, str]
|
|
1479
1594
|
""" Mount type of the antenna. Reserved keywords include: ”EQUATORIAL” - equatorial mount;
|
|
1480
|
-
”ALT-AZ
|
|
1481
|
-
"ALT-AZ+ROTATOR"
|
|
1595
|
+
”ALT-AZ”: azimuth-elevation mount;
|
|
1596
|
+
"ALT-AZ+ROTATOR": alt-az mount with feed rotator; introduced for ASKAP dishes;
|
|
1482
1597
|
"ALT-AZ+NASMYTH-R": Nasmyth mount with receivers at the right-hand side of the cabin. Many high-frequency antennas used for VLBI have such a mount typel;
|
|
1483
|
-
"ALT-AZ+NASMYTH-L
|
|
1484
|
-
|
|
1485
|
-
|
|
1598
|
+
"ALT-AZ+NASMYTH-L": Nasmyth mount with receivers at the left-hand side of the cabin.
|
|
1599
|
+
"ALT-AZ+BWG-R": alt-az mount that uses a Beam Wave Guide to bring the focus down to the pedestal. The receivers are at the right-hand side of the cabin (-R). Compared to the Nasmyth mounts there is an extra correction term because there are now two rotating mirrors. See https://arxiv.org/abs/2210.13381 for more details.
|
|
1600
|
+
"ALT-AZ+BWG-L": alt-az mount that uses a Beam Wave Guide, as above, but with receivers at the left-hand side of the cabin.
|
|
1601
|
+
”X-Y”: x-y mount;
|
|
1602
|
+
”SPACE-HALCA”: specific orientation model."""
|
|
1486
1603
|
telescope_name: Coord[AntennaName, str]
|
|
1487
1604
|
""" Useful when data is combined from mutiple arrays for example ACA + ALMA. """
|
|
1488
1605
|
receptor_label: Coord[ReceptorLabel, str]
|
|
@@ -1778,7 +1895,7 @@ class SystemCalibrationXds:
|
|
|
1778
1895
|
""" Midpoint of time for which this set of parameters is accurate. Labeled 'time' when interpolating to main time axis """
|
|
1779
1896
|
time_system_cal: Optional[Coordof[TimeSystemCalCoordArray]] = None
|
|
1780
1897
|
""" Midpoint of time for which this set of parameters is accurate. Labeled 'time_system_cal' when not interpolating to main time axis """
|
|
1781
|
-
frequency: Optional[Coordof[
|
|
1898
|
+
frequency: Optional[Coordof[FrequencyArray]] = None
|
|
1782
1899
|
""" """
|
|
1783
1900
|
frequency_system_cal: Optional[Coord[FrequencySystemCal, int]] = None
|
|
1784
1901
|
"""TODO: What is this?"""
|
|
@@ -1915,6 +2032,8 @@ class VisibilityXds:
|
|
|
1915
2032
|
"""
|
|
1916
2033
|
Labels for polarization types, e.g. ``['XX','XY','YX','YY']``, ``['RR','RL','LR','LL']``.
|
|
1917
2034
|
"""
|
|
2035
|
+
field_name: Coordof[Coord[Time, str]]
|
|
2036
|
+
"""Field name."""
|
|
1918
2037
|
|
|
1919
2038
|
# --- Required data variables ---
|
|
1920
2039
|
|
|
@@ -1927,17 +2046,21 @@ class VisibilityXds:
|
|
|
1927
2046
|
"""Antenna name for 2nd antenna in baseline. Maps to ``attrs['antenna_xds'].antenna_name``"""
|
|
1928
2047
|
|
|
1929
2048
|
# --- Required Attributes ---
|
|
1930
|
-
partition_info: Attr[PartitionInfoDict]
|
|
2049
|
+
# partition_info: Attr[PartitionInfoDict]
|
|
1931
2050
|
observation_info: Attr[ObservationInfoDict]
|
|
1932
2051
|
processor_info: Attr[ProcessorInfoDict]
|
|
1933
|
-
|
|
2052
|
+
|
|
2053
|
+
data_groups: Attr[DataGroupsDict]
|
|
2054
|
+
""" Defines groups of correlated data + flag + weight + uvw variables. """
|
|
1934
2055
|
|
|
1935
2056
|
schema_version: Attr[str]
|
|
1936
|
-
"""Semantic version of
|
|
2057
|
+
"""Semantic version of MSv4 data format."""
|
|
2058
|
+
creator: Attr[CreatorDict]
|
|
2059
|
+
"""Creator information (software, version)."""
|
|
1937
2060
|
creation_date: Attr[str]
|
|
1938
|
-
"""Date visibility dataset was created
|
|
2061
|
+
"""Date visibility dataset was created. Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
|
|
1939
2062
|
|
|
1940
|
-
type: Attr[Literal["visibility"]] = "visibility"
|
|
2063
|
+
type: Attr[Literal["visibility", "radiometer"]] = "visibility"
|
|
1941
2064
|
"""
|
|
1942
2065
|
Dataset type
|
|
1943
2066
|
"""
|
|
@@ -1953,7 +2076,7 @@ class VisibilityXds:
|
|
|
1953
2076
|
uvw_label: Optional[Coordof[UvwLabelArray]] = None
|
|
1954
2077
|
""" u,v,w """
|
|
1955
2078
|
scan_name: Optional[Coord[Time, str]] = None
|
|
1956
|
-
"""
|
|
2079
|
+
"""Scan name to identify data taken in the same logical scan."""
|
|
1957
2080
|
|
|
1958
2081
|
# --- Optional data variables / arrays ---
|
|
1959
2082
|
|
|
@@ -1967,7 +2090,6 @@ class VisibilityXds:
|
|
|
1967
2090
|
Data[
|
|
1968
2091
|
Union[
|
|
1969
2092
|
tuple[Time, BaselineId],
|
|
1970
|
-
tuple[Time, BaselineId, Frequency],
|
|
1971
2093
|
tuple[Time, BaselineId, Frequency, Polarization],
|
|
1972
2094
|
],
|
|
1973
2095
|
QuantityInSecondsArray,
|
|
@@ -1985,21 +2107,12 @@ class VisibilityXds:
|
|
|
1985
2107
|
"""
|
|
1986
2108
|
TIME_CENTROID_EXTRA_PRECISION: Optional[Dataof[TimeSamplingArray]] = None
|
|
1987
2109
|
"""Additional precision for ``TIME_CENTROID``"""
|
|
1988
|
-
EFFECTIVE_CHANNEL_WIDTH: Optional[Dataof[
|
|
2110
|
+
EFFECTIVE_CHANNEL_WIDTH: Optional[Dataof[EffectiveChannelWidthArray]] = None
|
|
1989
2111
|
"""The channel bandwidth that includes the effects of missing data."""
|
|
1990
|
-
FREQUENCY_CENTROID: Optional[Dataof[
|
|
2112
|
+
FREQUENCY_CENTROID: Optional[Dataof[FrequencyCentroidArray]] = None
|
|
1991
2113
|
"""Includes the effects of missing data unlike ``frequency``."""
|
|
1992
2114
|
|
|
1993
2115
|
# --- Optional Attributes ---
|
|
1994
|
-
pointing_xds: Optional[Attr[PointingXds]] = None
|
|
1995
|
-
system_calibration_xds: Optional[Attr[SystemCalibrationXds]] = None
|
|
1996
|
-
gain_curve_xds: Optional[Attr[GainCurveXds]] = None
|
|
1997
|
-
phase_calibration_xds: Optional[Attr[PhaseCalibrationXds]] = None
|
|
1998
|
-
weather_xds: Optional[Attr[WeatherXds]] = None
|
|
1999
|
-
phased_array_xds: Optional[Attr[PhasedArrayXds]] = None
|
|
2000
|
-
|
|
2001
|
-
xradio_version: Optional[Attr[str]] = None
|
|
2002
|
-
""" Version of XRADIO used if converted from MSv2. """
|
|
2003
2116
|
|
|
2004
2117
|
|
|
2005
2118
|
@xarray_dataset_schema
|
|
@@ -2020,21 +2133,27 @@ class SpectrumXds:
|
|
|
2020
2133
|
"""
|
|
2021
2134
|
Labels for polarization types, e.g. ``['XX','XY','YX','YY']``, ``['RR','RL','LR','LL']``.
|
|
2022
2135
|
"""
|
|
2136
|
+
field_name: Coordof[Coord[Time, str]]
|
|
2137
|
+
"""Field name."""
|
|
2023
2138
|
|
|
2024
2139
|
# --- Required data variables ---
|
|
2025
2140
|
SPECTRUM: Dataof[SpectrumArray]
|
|
2026
2141
|
"""Single dish data, either simulated or measured by an antenna."""
|
|
2027
2142
|
|
|
2028
2143
|
# --- Required Attributes ---
|
|
2029
|
-
partition_info: Attr[PartitionInfoDict]
|
|
2144
|
+
# partition_info: Attr[PartitionInfoDict]
|
|
2030
2145
|
observation_info: Attr[ObservationInfoDict]
|
|
2031
2146
|
processor_info: Attr[ProcessorInfoDict]
|
|
2032
|
-
|
|
2147
|
+
|
|
2148
|
+
data_groups: Attr[DataGroupsDict]
|
|
2149
|
+
""" Defines groups of correlated data + flag + weight variables. """
|
|
2033
2150
|
|
|
2034
2151
|
schema_version: Attr[str]
|
|
2035
|
-
"""Semantic version of
|
|
2152
|
+
"""Semantic version of MSv4 data format."""
|
|
2153
|
+
creator: Attr[CreatorDict]
|
|
2154
|
+
"""Creator information (software, version)."""
|
|
2036
2155
|
creation_date: Attr[str]
|
|
2037
|
-
"""Date
|
|
2156
|
+
"""Date spectrum dataset was created . Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
|
|
2038
2157
|
|
|
2039
2158
|
type: Attr[Literal["spectrum"]] = "spectrum"
|
|
2040
2159
|
"""
|
|
@@ -2062,7 +2181,6 @@ class SpectrumXds:
|
|
|
2062
2181
|
Data[
|
|
2063
2182
|
Union[
|
|
2064
2183
|
tuple[Time, AntennaName],
|
|
2065
|
-
tuple[Time, AntennaName, Frequency],
|
|
2066
2184
|
tuple[Time, AntennaName, Frequency, Polarization],
|
|
2067
2185
|
],
|
|
2068
2186
|
QuantityInSecondsArray,
|
|
@@ -2080,18 +2198,7 @@ class SpectrumXds:
|
|
|
2080
2198
|
"""
|
|
2081
2199
|
TIME_CENTROID_EXTRA_PRECISION: Optional[Dataof[TimeSamplingArray]] = None
|
|
2082
2200
|
"""Additional precision for ``TIME_CENTROID``"""
|
|
2083
|
-
EFFECTIVE_CHANNEL_WIDTH: Optional[Dataof[
|
|
2201
|
+
EFFECTIVE_CHANNEL_WIDTH: Optional[Dataof[EffectiveChannelWidthArray]] = None
|
|
2084
2202
|
"""The channel bandwidth that includes the effects of missing data."""
|
|
2085
|
-
FREQUENCY_CENTROID: Optional[Dataof[
|
|
2203
|
+
FREQUENCY_CENTROID: Optional[Dataof[FrequencyCentroidArray]] = None
|
|
2086
2204
|
"""Includes the effects of missing data unlike ``frequency``."""
|
|
2087
|
-
|
|
2088
|
-
# --- Optional Attributes ---
|
|
2089
|
-
pointing_xds: Optional[Attr[PointingXds]] = None
|
|
2090
|
-
system_calibration_xds: Optional[Attr[SystemCalibrationXds]] = None
|
|
2091
|
-
gain_curve_xds: Optional[Attr[GainCurveXds]] = None
|
|
2092
|
-
phase_calibration_xds: Optional[Attr[PhaseCalibrationXds]] = None
|
|
2093
|
-
weather_xds: Optional[Attr[WeatherXds]] = None
|
|
2094
|
-
phased_array_xds: Optional[Attr[PhasedArrayXds]] = None
|
|
2095
|
-
|
|
2096
|
-
xradio_version: Optional[Attr[str]] = None
|
|
2097
|
-
""" Version of XRADIO used if converted from MSv2. """
|
xradio/schema/bases.py
CHANGED
|
@@ -397,11 +397,15 @@ def xarray_dataset_schema(cls):
|
|
|
397
397
|
cls = dataclasses.dataclass(cls, init=True, repr=False, eq=False, frozen=True)
|
|
398
398
|
|
|
399
399
|
# Make schema
|
|
400
|
-
|
|
400
|
+
schema = dataclass.xarray_dataclass_to_dataset_schema(cls)
|
|
401
|
+
cls.__xradio_dataset_schema = schema
|
|
401
402
|
|
|
402
403
|
# Replace __new__
|
|
403
404
|
cls.__new__ = _dataset_new
|
|
404
405
|
|
|
406
|
+
# Register type
|
|
407
|
+
check.register_dataset_type(schema)
|
|
408
|
+
|
|
405
409
|
return cls
|
|
406
410
|
|
|
407
411
|
|
xradio/schema/check.py
CHANGED
|
@@ -2,6 +2,7 @@ import dataclasses
|
|
|
2
2
|
import typing
|
|
3
3
|
import inspect
|
|
4
4
|
import functools
|
|
5
|
+
import warnings
|
|
5
6
|
|
|
6
7
|
import xarray
|
|
7
8
|
import numpy
|
|
@@ -173,7 +174,9 @@ def check_array(
|
|
|
173
174
|
|
|
174
175
|
|
|
175
176
|
def check_dataset(
|
|
176
|
-
dataset: xarray.Dataset,
|
|
177
|
+
dataset: xarray.Dataset,
|
|
178
|
+
schema: typing.Union[type, metamodel.DatasetSchema],
|
|
179
|
+
allow_superflous_dims: typing.Set[str] = frozenset(),
|
|
177
180
|
) -> SchemaIssues:
|
|
178
181
|
"""
|
|
179
182
|
Check whether an xarray DataArray conforms to a schema
|
|
@@ -196,7 +199,12 @@ def check_dataset(
|
|
|
196
199
|
)
|
|
197
200
|
|
|
198
201
|
# Check dimensions. Order does not matter on datasets
|
|
199
|
-
issues = check_dimensions(
|
|
202
|
+
issues = check_dimensions(
|
|
203
|
+
dataset.dims,
|
|
204
|
+
schema.dimensions,
|
|
205
|
+
check_order=False,
|
|
206
|
+
allow_superflous=allow_superflous_dims,
|
|
207
|
+
)
|
|
200
208
|
|
|
201
209
|
# Check attributes
|
|
202
210
|
issues += check_attributes(dataset.attrs, schema.attributes)
|
|
@@ -211,7 +219,10 @@ def check_dataset(
|
|
|
211
219
|
|
|
212
220
|
|
|
213
221
|
def check_dimensions(
|
|
214
|
-
dims: [str],
|
|
222
|
+
dims: [str],
|
|
223
|
+
expected: [[str]],
|
|
224
|
+
check_order: bool = True,
|
|
225
|
+
allow_superflous: typing.Set[str] = frozenset(),
|
|
215
226
|
) -> SchemaIssues:
|
|
216
227
|
"""
|
|
217
228
|
Check whether a dimension list conforms to a schema
|
|
@@ -230,7 +241,7 @@ def check_dimensions(
|
|
|
230
241
|
exp_dims_set = set(exp_dims)
|
|
231
242
|
|
|
232
243
|
# No match? Continue, but take note of best match
|
|
233
|
-
if exp_dims_set != dims_set:
|
|
244
|
+
if exp_dims_set - allow_superflous != dims_set - allow_superflous:
|
|
234
245
|
diff = len(dims_set.symmetric_difference(exp_dims_set))
|
|
235
246
|
if best is None or diff < best_diff:
|
|
236
247
|
best = exp_dims_set
|
|
@@ -253,7 +264,7 @@ def check_dimensions(
|
|
|
253
264
|
)
|
|
254
265
|
|
|
255
266
|
# Dimensionality not supported - try to give a helpful suggestion
|
|
256
|
-
hint_remove = [f"'{hint}'" for hint in dims_set - best]
|
|
267
|
+
hint_remove = [f"'{hint}'" for hint in (dims_set - best) - allow_superflous]
|
|
257
268
|
hint_add = [f"'{hint}'" for hint in best - dims_set]
|
|
258
269
|
if hint_remove and hint_add:
|
|
259
270
|
message = f"Unexpected coordinates, replace {','.join(hint_remove)} by {','.join(hint_add)}?"
|
|
@@ -560,6 +571,87 @@ def _check_value_union(val, ann):
|
|
|
560
571
|
return args_issues
|
|
561
572
|
|
|
562
573
|
|
|
574
|
+
_DATASET_TYPES = {}
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def register_dataset_type(schema: metamodel.DatasetSchema):
|
|
578
|
+
"""
|
|
579
|
+
Registers the given schema for usage with :py:meth:`check_datatree`
|
|
580
|
+
|
|
581
|
+
This looks for a ``type`` attribute in the dataset schema, which
|
|
582
|
+
must have a :py:class:`typing.Literal` type annotation specifying
|
|
583
|
+
the type name of the dataset
|
|
584
|
+
|
|
585
|
+
:param schema: Schema to register
|
|
586
|
+
"""
|
|
587
|
+
|
|
588
|
+
# Find type attribute
|
|
589
|
+
for attr in schema.attributes:
|
|
590
|
+
if attr.name != "type":
|
|
591
|
+
continue
|
|
592
|
+
|
|
593
|
+
# Type should be a kind of literal
|
|
594
|
+
if typing.get_origin(attr.typ) is not typing.Literal:
|
|
595
|
+
warnings.warn(
|
|
596
|
+
f"In dataset schema {schema.schema_name}:"
|
|
597
|
+
'Attribute "type" should be a literal!'
|
|
598
|
+
)
|
|
599
|
+
continue
|
|
600
|
+
|
|
601
|
+
# Register type names
|
|
602
|
+
for typ in typing.get_args(attr.typ):
|
|
603
|
+
_DATASET_TYPES[typ] = schema
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def check_datatree(
|
|
607
|
+
datatree: xarray.DataTree,
|
|
608
|
+
):
|
|
609
|
+
"""
|
|
610
|
+
Check datatree for schema conformance
|
|
611
|
+
|
|
612
|
+
This is the case if all nodes containing data
|
|
613
|
+
|
|
614
|
+
This looks for a ``type`` attribute in the dataset schema, which
|
|
615
|
+
must have a :py:class:`typing.Literal` type annotation specifying
|
|
616
|
+
the type name of the dataset
|
|
617
|
+
|
|
618
|
+
:param schema: Schema to register
|
|
619
|
+
"""
|
|
620
|
+
|
|
621
|
+
# Loop through all groups in datatree
|
|
622
|
+
issues = SchemaIssues()
|
|
623
|
+
for xds_name in datatree.groups:
|
|
624
|
+
|
|
625
|
+
# Ignore any leaf without data
|
|
626
|
+
node = datatree[xds_name]
|
|
627
|
+
if not node.has_data:
|
|
628
|
+
continue
|
|
629
|
+
|
|
630
|
+
# Look up schema
|
|
631
|
+
schema = _DATASET_TYPES.get(node.attrs.get("type"))
|
|
632
|
+
if schema is None:
|
|
633
|
+
issues.add(
|
|
634
|
+
SchemaIssue(
|
|
635
|
+
[("", xds_name)],
|
|
636
|
+
message="Unknown dataset type!",
|
|
637
|
+
found=typ,
|
|
638
|
+
expected=list(schemas.keys()),
|
|
639
|
+
)
|
|
640
|
+
)
|
|
641
|
+
continue
|
|
642
|
+
|
|
643
|
+
# Determine dimensions inherited from parent
|
|
644
|
+
# (they might show up as "superflous" for the child schema)
|
|
645
|
+
parent_dims = frozenset()
|
|
646
|
+
if node.parent is not None:
|
|
647
|
+
parent_dims = set(node.parent.dims)
|
|
648
|
+
|
|
649
|
+
# Check schema
|
|
650
|
+
issues += check_dataset(node.dataset, schema, parent_dims).at_path("", xds_name)
|
|
651
|
+
|
|
652
|
+
return issues
|
|
653
|
+
|
|
654
|
+
|
|
563
655
|
def schema_checked(fn, check_parameters: bool = True, check_return: bool = True):
|
|
564
656
|
"""
|
|
565
657
|
Function decorator to check parameters and return value for
|