xradio 0.0.40__py3-none-any.whl → 0.0.42__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/_utils/coord_math.py +100 -0
- xradio/_utils/list_and_array.py +49 -4
- xradio/_utils/schema.py +36 -16
- xradio/image/_util/_casacore/xds_from_casacore.py +5 -5
- xradio/image/_util/_casacore/xds_to_casacore.py +12 -11
- xradio/image/_util/_fits/xds_from_fits.py +18 -17
- xradio/image/_util/_zarr/zarr_low_level.py +29 -12
- xradio/image/_util/common.py +1 -1
- xradio/image/_util/image_factory.py +1 -1
- xradio/measurement_set/__init__.py +18 -0
- xradio/measurement_set/_utils/__init__.py +5 -0
- xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/load_main_table.py +1 -1
- xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/read.py +15 -1
- xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/conversion.py +186 -84
- xradio/measurement_set/_utils/_msv2/create_antenna_xds.py +535 -0
- xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/create_field_and_source_xds.py +146 -58
- xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +203 -0
- xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +550 -0
- xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/subtables.py +1 -1
- xradio/{vis/_vis_utils → measurement_set/_utils}/_utils/xds_helper.py +1 -1
- xradio/{vis/_vis_utils/ms.py → measurement_set/_utils/msv2.py} +4 -4
- xradio/{vis/_vis_utils → measurement_set/_utils}/zarr.py +3 -3
- xradio/{vis → measurement_set}/convert_msv2_to_processing_set.py +9 -2
- xradio/{vis → measurement_set}/load_processing_set.py +16 -20
- xradio/measurement_set/measurement_set_xds.py +83 -0
- xradio/{vis/read_processing_set.py → measurement_set/open_processing_set.py} +25 -34
- xradio/measurement_set/processing_set.py +777 -0
- xradio/measurement_set/schema.py +1979 -0
- xradio/schema/check.py +42 -22
- xradio/schema/dataclass.py +56 -6
- xradio/sphinx/__init__.py +12 -0
- xradio/sphinx/schema_table.py +351 -0
- {xradio-0.0.40.dist-info → xradio-0.0.42.dist-info}/METADATA +17 -15
- xradio-0.0.42.dist-info/RECORD +76 -0
- {xradio-0.0.40.dist-info → xradio-0.0.42.dist-info}/WHEEL +1 -1
- xradio/_utils/common.py +0 -101
- xradio/vis/__init__.py +0 -14
- xradio/vis/_processing_set.py +0 -302
- xradio/vis/_vis_utils/__init__.py +0 -5
- xradio/vis/_vis_utils/_ms/create_antenna_xds.py +0 -482
- xradio/vis/_vis_utils/_ms/msv4_infos.py +0 -0
- xradio/vis/_vis_utils/_ms/msv4_sub_xdss.py +0 -306
- xradio/vis/schema.py +0 -1102
- xradio-0.0.40.dist-info/RECORD +0 -73
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/load.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/read_main_table.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/read_subtables.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/table_query.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/write.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/_tables/write_exp_api.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/chunks.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/descr.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/msv2_msv3.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/msv2_to_msv4_meta.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/optimised_functions.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/partition_queries.py +0 -0
- /xradio/{vis/_vis_utils/_ms → measurement_set/_utils/_msv2}/partitions.py +0 -0
- /xradio/{vis/_vis_utils → measurement_set/_utils}/_utils/cds.py +0 -0
- /xradio/{vis/_vis_utils → measurement_set/_utils}/_utils/partition_attrs.py +0 -0
- /xradio/{vis/_vis_utils → measurement_set/_utils}/_utils/stokes_types.py +0 -0
- /xradio/{vis/_vis_utils → measurement_set/_utils}/_zarr/encoding.py +0 -0
- /xradio/{vis/_vis_utils → measurement_set/_utils}/_zarr/read.py +0 -0
- /xradio/{vis/_vis_utils → measurement_set/_utils}/_zarr/write.py +0 -0
- {xradio-0.0.40.dist-info → xradio-0.0.42.dist-info}/LICENSE.txt +0 -0
- {xradio-0.0.40.dist-info → xradio-0.0.42.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
xradio/__init__.py,sha256=WHBhQWQie3YQqfIxQBL3LKiKuUcN7ZL7sPMEcdWOp5E,382
|
|
2
|
+
xradio/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
xradio/_utils/coord_math.py,sha256=n4Td6jcEX4vM49Xseuwrg6USylTGsySS6CND93DEG_8,3587
|
|
4
|
+
xradio/_utils/list_and_array.py,sha256=epw4IRnQUWP9x5mdsZPstECD7jUjXx7y9RgMdCDolEg,4291
|
|
5
|
+
xradio/_utils/schema.py,sha256=p6Iet4Lfs1qUI3vWMUr-Sh2PsilSoSz9tqSP43U_0uQ,7398
|
|
6
|
+
xradio/_utils/_casacore/tables.py,sha256=aq6E_4RRAHdTBCwMKrVil1cWhFU2O980DNH9IlRKXLw,1280
|
|
7
|
+
xradio/_utils/zarr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
xradio/_utils/zarr/common.py,sha256=egj3Zma0BUK0msOBDozMa-62rHrcxrjCNE5XkkZUq70,5332
|
|
9
|
+
xradio/image/__init__.py,sha256=HAD0GfopIbhdxOYckyW6S9US_dSWmZrwIl3FHUzZwrE,435
|
|
10
|
+
xradio/image/image.py,sha256=QoJ_BTLoMfeXJzU1yvtidBIhaMmjNA5_-6C3FWJRUeI,15635
|
|
11
|
+
xradio/image/_util/__init__.py,sha256=M9lxD1Gc7kv0ucDEDbjLRuIEuESev-IG8j9EaCKUAkA,77
|
|
12
|
+
xradio/image/_util/casacore.py,sha256=DmBTHUQ6870N5ARuFnYSfjZSLniJYgsjrsICUlCREYM,4234
|
|
13
|
+
xradio/image/_util/common.py,sha256=gCVIq547PZMOM7urkdwPXyKcfstD-loJFcf6YGa8CGM,9039
|
|
14
|
+
xradio/image/_util/fits.py,sha256=gyGm06fuCKqVGK7uv-ObvQNfFawUDsIOa_nQyklM3Aw,329
|
|
15
|
+
xradio/image/_util/image_factory.py,sha256=-ZCDkCg25HMN4ubDxeBPv24HsEpYB5_zJYajgPx6_pg,10514
|
|
16
|
+
xradio/image/_util/zarr.py,sha256=lhQqVRC1GEWClG3zRbuDr2IlQBfXeDqaLUJIN-MVMxA,1652
|
|
17
|
+
xradio/image/_util/_casacore/__init__.py,sha256=OlsiRE40o1jSbBI4khgQQzgfDYbAlOMKIhO4UFlbGhg,41
|
|
18
|
+
xradio/image/_util/_casacore/common.py,sha256=ky999eTCWta8w-uIs-7P7rPhZRLuh9yTuQXAxPvaPm4,1579
|
|
19
|
+
xradio/image/_util/_casacore/xds_from_casacore.py,sha256=o03KTPEyJpG78GJJeT2gqYZWe7gqqWQ9ned0UEQw710,42596
|
|
20
|
+
xradio/image/_util/_casacore/xds_to_casacore.py,sha256=qSoKemfH4wX7-7QrEQa_y3Qitn7NCIoCV7fLfDhaaUM,15427
|
|
21
|
+
xradio/image/_util/_fits/xds_from_fits.py,sha256=MNlZfW0exYBlCoMCA_Nd84eggNw_W8WhjSICgAihyLk,28543
|
|
22
|
+
xradio/image/_util/_zarr/common.py,sha256=apMX_bF4Hr3pFGjnDFpp36KgmhTYAPBZquNkjBHrsXk,307
|
|
23
|
+
xradio/image/_util/_zarr/xds_from_zarr.py,sha256=4b6KHmAcnrhBbCi-Z7e3Lm6l6wziJL1zaNIohmPAYDk,3601
|
|
24
|
+
xradio/image/_util/_zarr/xds_to_zarr.py,sha256=wogXbwX8n3Sl9PHoc3_Y_LBowQsQ-94HZQFZ5NcxUZA,1624
|
|
25
|
+
xradio/image/_util/_zarr/zarr_low_level.py,sha256=fVaPnxYazz6UDLBZuyUOekZKQ945OwhfBHeNeDgnW0w,13338
|
|
26
|
+
xradio/measurement_set/__init__.py,sha256=0M0Zl5uKozIp5mgPhNaIoal_UuZc1HCA6_zQOhLFo8A,567
|
|
27
|
+
xradio/measurement_set/convert_msv2_to_processing_set.py,sha256=hviYPhiytkC8PqTPQvEp5ttKZs6MoDC0Rh57nqIgqMQ,6426
|
|
28
|
+
xradio/measurement_set/load_processing_set.py,sha256=RedC4i4dOHzgYiz_C0P-3F0PwvEGUomvq_ilpcfUCco,5540
|
|
29
|
+
xradio/measurement_set/measurement_set_xds.py,sha256=i1CQ8oz9lvRDpwkuRPYJPbbW9SB5oght4DrrfAkllAU,2953
|
|
30
|
+
xradio/measurement_set/open_processing_set.py,sha256=533fwEP4pJIBB-NdwFttbobVb8zEXsblvDTjF4ptTDU,3831
|
|
31
|
+
xradio/measurement_set/processing_set.py,sha256=NaxnJw2temC3N5V0ohvp5CLewAJHAm26TpTfZ0GXjuw,29733
|
|
32
|
+
xradio/measurement_set/schema.py,sha256=e5bdPw9GHd0k2RGUL6ozNNz8eAz-dhru8XaLmBmZI7I,73511
|
|
33
|
+
xradio/measurement_set/_utils/__init__.py,sha256=XE-h1yMfr6tVD6gdUwXO1CVq5SQ6kD_oj-e5TFwslds,97
|
|
34
|
+
xradio/measurement_set/_utils/msv2.py,sha256=7hnZMFoQ-s1g0ATjEupLvtdqQCdroPv-Rl5OwjqXjh8,4430
|
|
35
|
+
xradio/measurement_set/_utils/zarr.py,sha256=ehXlu0Xh_UZ5Xm2RnHCxESsRZ26c3DQAO5rqMK5MwTk,3947
|
|
36
|
+
xradio/measurement_set/_utils/_msv2/chunks.py,sha256=JTPk3il6fk570BjWZMoOAtsbvnLmqPcBv9EPY6A2yOs,2964
|
|
37
|
+
xradio/measurement_set/_utils/_msv2/conversion.py,sha256=LeHZomIbQcSXwprYvgilOUvzhIF3nuzonovl7_C9vNs,42387
|
|
38
|
+
xradio/measurement_set/_utils/_msv2/create_antenna_xds.py,sha256=HhNieztzuP0Fg898mVHFHaDoaLrxw7JS98osuDSYHnI,18333
|
|
39
|
+
xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py,sha256=jpAaNV76iTrRn-vOTPdihByaoZwl1viyK5VZNNOGdTE,34159
|
|
40
|
+
xradio/measurement_set/_utils/_msv2/descr.py,sha256=dYK8mhXxODIh-dfqaOm-YZb7kmoN1N2golX_RFncO94,5215
|
|
41
|
+
xradio/measurement_set/_utils/_msv2/msv2_msv3.py,sha256=9AKs2HWly7Ivv_Cjr11dIPGmm33_rtSBoGF9wN5ZwEQ,116
|
|
42
|
+
xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py,sha256=gk9gU7g2Lk7dmaiLW8qecOEt574pRtGsCHnUnHXM3D0,1614
|
|
43
|
+
xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py,sha256=kQpKNvgIki_ZIpC-lbKRqCKah7aLBoy5Q_NH1Q2vz3g,6895
|
|
44
|
+
xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py,sha256=6zEWiTraYGekZ9vb-V7OZ1kLxspzOzOYjETZWH26SCo,20148
|
|
45
|
+
xradio/measurement_set/_utils/_msv2/optimised_functions.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
|
+
xradio/measurement_set/_utils/_msv2/partition_queries.py,sha256=hEe3VAzGqtEPg3X4GUhvHaxyesjS6WVy5et421qSdZg,14573
|
|
47
|
+
xradio/measurement_set/_utils/_msv2/partitions.py,sha256=_KhRq8bSx2QxuWp9K57fLoLxcU6kvJ35e6wvJ-THbwc,12979
|
|
48
|
+
xradio/measurement_set/_utils/_msv2/subtables.py,sha256=_mpOOtHexqhiqEKt7S4LVqImJoNMJKSY18vNVw83r_U,3945
|
|
49
|
+
xradio/measurement_set/_utils/_msv2/_tables/load.py,sha256=IR3fdKlq8rgH4bHmB1JTtB5gSGuITIvErJEVjUA8rWM,1799
|
|
50
|
+
xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py,sha256=IOGHMyemLbc6kJZC81LE6l0gVdgXuIFmDty2pxb5rr0,14806
|
|
51
|
+
xradio/measurement_set/_utils/_msv2/_tables/read.py,sha256=OV6Zfoz1mhOK4Fv4SeQ_M9f600nHK-BQfJ551Wmr5hA,42947
|
|
52
|
+
xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py,sha256=8AbNt-AxrhPK3EPRa7xqJXffxzIgfVsv1BDfoVJEXLU,26056
|
|
53
|
+
xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py,sha256=JM6pGUQtjQR881u9VqakmbJjppEFq-EVKnEZ14JqnAw,12438
|
|
54
|
+
xradio/measurement_set/_utils/_msv2/_tables/table_query.py,sha256=q8EGFf_zIwHcHnvFJOn8hPh8zFZQ3f7BGbXvL3bHad4,555
|
|
55
|
+
xradio/measurement_set/_utils/_msv2/_tables/write.py,sha256=43XQ-tHhbhex0eUTRknNpPEEOnNR-w1lGCox9WZ9NHE,9540
|
|
56
|
+
xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py,sha256=GDEll8nMwkQGc6vosu4UddFL5_ld7WurRgF9hYFTRmU,15511
|
|
57
|
+
xradio/measurement_set/_utils/_utils/cds.py,sha256=OpvKowSheIthUbcPEv2AoKmxlEt3DqJZS5C1AYh5z10,1179
|
|
58
|
+
xradio/measurement_set/_utils/_utils/partition_attrs.py,sha256=JaePHts_A0EbB4K-0a_uC98RZ2EmfjB9pDSEI11oAwk,3401
|
|
59
|
+
xradio/measurement_set/_utils/_utils/stokes_types.py,sha256=DMa8TmmS7BQ99Xm8c7ZjcRapMtLbrKVxrt4f0qUIOvg,561
|
|
60
|
+
xradio/measurement_set/_utils/_utils/xds_helper.py,sha256=3BYwpeklJCRJCkkwNU54JbFgibaQOffK6vJzNcwicHI,13229
|
|
61
|
+
xradio/measurement_set/_utils/_zarr/encoding.py,sha256=GENIlThV6a9CUCL6gIGlu9c6NR3OFWNos6mpxZjMwDc,536
|
|
62
|
+
xradio/measurement_set/_utils/_zarr/read.py,sha256=O9DiwD2Gn8WiatQ-Q6WGGSwjsXwFktG4f81lM-mgcSg,7596
|
|
63
|
+
xradio/measurement_set/_utils/_zarr/write.py,sha256=k5IfqtI44Dm4KBDiKFGhL5hN7kwNOulvVHmeP5Mi7N4,10043
|
|
64
|
+
xradio/schema/__init__.py,sha256=EzEMnOtN8G_wdjo8QBRKfq5MrYgfr_nt1pfunlI6i6Q,733
|
|
65
|
+
xradio/schema/bases.py,sha256=5BiE6gAq2xmaJEyiaGbpCSoNek83ly9f0R0Rv1rx9DM,17081
|
|
66
|
+
xradio/schema/check.py,sha256=AWdqGwcbH1wW3_sWSAeILZd9L8_e3Ae5L9TURt3ns1k,19304
|
|
67
|
+
xradio/schema/dataclass.py,sha256=w6FbFtmGnAX4SYwYar7v8-YFf6j40G7g_jvIfVCuxjc,14087
|
|
68
|
+
xradio/schema/metamodel.py,sha256=WjtW7pAVzcjLRWifRH3sQoOiN6TV810hARpOIz1M_gw,3845
|
|
69
|
+
xradio/schema/typing.py,sha256=8-o6fZd99kJ4FVdgBYRTIRJ-wDqpcUNXzCTfJvl3TIw,10439
|
|
70
|
+
xradio/sphinx/__init__.py,sha256=VGY-7Ty3q67qpnBee0-znbiJ-Iy0F93UO--IpjEdHXc,380
|
|
71
|
+
xradio/sphinx/schema_table.py,sha256=YTQvK-VOBIpFtcx7sjcaMod4OSbl0uowelYIcdP3oVg,11878
|
|
72
|
+
xradio-0.0.42.dist-info/LICENSE.txt,sha256=9CYIJt7riOXo9AD0eXBZviLxo_HebD-2JJI8oiWtzfg,1807
|
|
73
|
+
xradio-0.0.42.dist-info/METADATA,sha256=nuEv90nQvqHhEmGwQ53zU3xaIoE6ZaTLkF-mDhNYa6E,4488
|
|
74
|
+
xradio-0.0.42.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
75
|
+
xradio-0.0.42.dist-info/top_level.txt,sha256=dQu27fGBZJ2Yk-gW5XeD-dZ76Xa4Xcvk60Vz-dwXp7k,7
|
|
76
|
+
xradio-0.0.42.dist-info/RECORD,,
|
xradio/_utils/common.py
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
_deg_to_rad = np.pi / 180
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def cast_to_str(x):
|
|
7
|
-
if isinstance(x, list):
|
|
8
|
-
return x[0]
|
|
9
|
-
else:
|
|
10
|
-
return x
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def get_pad_value(col_dtype: np.dtype) -> object:
|
|
14
|
-
"""
|
|
15
|
-
Produce a padding/missing/nan value appropriate for a casacore data column
|
|
16
|
-
(for when we need to pad data vars coming from columns with rows of
|
|
17
|
-
variable size array values)
|
|
18
|
-
|
|
19
|
-
Parameters
|
|
20
|
-
----------
|
|
21
|
-
col_dtype : dtype
|
|
22
|
-
dtype of data being loaded from a table column
|
|
23
|
-
|
|
24
|
-
Returns
|
|
25
|
-
-------
|
|
26
|
-
object
|
|
27
|
-
pad value ("missing" / "fill") for the type given
|
|
28
|
-
"""
|
|
29
|
-
# Fill values for missing/NaN data in integer variables, based on usual
|
|
30
|
-
# numpy fill values. See https://github.com/numpy/numpy/issues/21166,
|
|
31
|
-
# https://github.com/casangi/xradio/issues/219, https://github.com/casangi/xradio/pull/177
|
|
32
|
-
fill_value_int32 = np.int32(-2147483648)
|
|
33
|
-
fill_value_int64 = np.int64(-9223372036854775808)
|
|
34
|
-
|
|
35
|
-
if col_dtype == np.int32:
|
|
36
|
-
return fill_value_int32
|
|
37
|
-
elif col_dtype == np.int64 or col_dtype == "int":
|
|
38
|
-
return fill_value_int64
|
|
39
|
-
elif np.issubdtype(col_dtype, np.floating):
|
|
40
|
-
return np.nan
|
|
41
|
-
elif np.issubdtype(col_dtype, np.complexfloating):
|
|
42
|
-
return complex(np.nan, np.nan)
|
|
43
|
-
elif np.issubdtype(col_dtype, np.bool_):
|
|
44
|
-
return False
|
|
45
|
-
elif np.issubdtype(col_dtype, str):
|
|
46
|
-
return ""
|
|
47
|
-
else:
|
|
48
|
-
raise RuntimeError(
|
|
49
|
-
"Padding / missing value not defined for the type requested: "
|
|
50
|
-
f"{col_dtype} (of type: {type(col_dtype)})"
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def convert_to_si_units(xds):
|
|
55
|
-
for data_var in xds.data_vars:
|
|
56
|
-
if "units" in xds[data_var].attrs:
|
|
57
|
-
for u_i, u in enumerate(xds[data_var].attrs["units"]):
|
|
58
|
-
if u == "km":
|
|
59
|
-
xds[data_var][..., u_i] = xds[data_var][..., u_i] * 1e3
|
|
60
|
-
xds[data_var].attrs["units"][u_i] = "m"
|
|
61
|
-
if u == "km/s":
|
|
62
|
-
xds[data_var][..., u_i] = xds[data_var][..., u_i] * 1e3
|
|
63
|
-
xds[data_var].attrs["units"][u_i] = "m/s"
|
|
64
|
-
if u == "deg":
|
|
65
|
-
xds[data_var][..., u_i] = xds[data_var][..., u_i] * np.pi / 180
|
|
66
|
-
xds[data_var].attrs["units"][u_i] = "rad"
|
|
67
|
-
if u == "Au" or u == "AU":
|
|
68
|
-
xds[data_var][..., u_i] = xds[data_var][..., u_i] * 149597870700
|
|
69
|
-
xds[data_var].attrs["units"][u_i] = "m"
|
|
70
|
-
if u == "Au/d" or u == "AU/d":
|
|
71
|
-
xds[data_var][..., u_i] = (
|
|
72
|
-
xds[data_var][..., u_i] * 149597870700 / 86400
|
|
73
|
-
)
|
|
74
|
-
xds[data_var].attrs["units"][u_i] = "m/s"
|
|
75
|
-
if u == "arcsec":
|
|
76
|
-
xds[data_var][..., u_i] = xds[data_var][..., u_i] * np.pi / 648000
|
|
77
|
-
xds[data_var].attrs["units"][u_i] = "rad"
|
|
78
|
-
return xds
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def add_position_offsets(dv_1, dv_2):
|
|
82
|
-
# Fun with angles: We are adding angles together. We need to make sure that the results are between -pi and pi.
|
|
83
|
-
new_pos = dv_1 + dv_2
|
|
84
|
-
|
|
85
|
-
while np.any(new_pos[:, 0] > np.pi) or np.any(new_pos[:, 0] < -np.pi):
|
|
86
|
-
new_pos[:, 0] = np.where(
|
|
87
|
-
new_pos[:, 0] > np.pi, new_pos[:, 0] - 2 * np.pi, new_pos[:, 0]
|
|
88
|
-
)
|
|
89
|
-
new_pos[:, 0] = np.where(
|
|
90
|
-
new_pos[:, 0] < -np.pi, new_pos[:, 0] + 2 * np.pi, new_pos[:, 0]
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
while np.any(new_pos[:, 1] > np.pi / 2) or np.any(new_pos[:, 1] < -np.pi / 2):
|
|
94
|
-
new_pos[:, 1] = np.where(
|
|
95
|
-
new_pos[:, 1] > np.pi / 2, new_pos[:, 1] - np.pi, new_pos[:, 1]
|
|
96
|
-
)
|
|
97
|
-
new_pos[:, 1] = np.where(
|
|
98
|
-
new_pos[:, 1] < -np.pi / 2, new_pos[:, 1] + np.pi, new_pos[:, 1]
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
return new_pos
|
xradio/vis/__init__.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from .read_processing_set import read_processing_set
|
|
2
|
-
from .load_processing_set import load_processing_set
|
|
3
|
-
from .convert_msv2_to_processing_set import convert_msv2_to_processing_set
|
|
4
|
-
|
|
5
|
-
from .schema import VisibilityXds
|
|
6
|
-
|
|
7
|
-
__all__ = [
|
|
8
|
-
"read_processing_set",
|
|
9
|
-
"load_processing_set",
|
|
10
|
-
"convert_msv2_to_processing_set",
|
|
11
|
-
"VisibilityXds",
|
|
12
|
-
"PointingXds",
|
|
13
|
-
"AntennaXds",
|
|
14
|
-
]
|
xradio/vis/_processing_set.py
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import pandas as pd
|
|
2
|
-
from xradio._utils.list_and_array import to_list
|
|
3
|
-
import numbers
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class processing_set(dict):
|
|
7
|
-
"""
|
|
8
|
-
A dictionary subclass representing a Processing Set (PS) that is a set of Measurement Sets v4 (MS).
|
|
9
|
-
|
|
10
|
-
This class extends the built-in `dict` class and provides additional methods for manipulating and selecting subsets of the Processing Set.
|
|
11
|
-
|
|
12
|
-
Attributes:
|
|
13
|
-
meta (dict): A dictionary containing metadata information about the Processing Set.
|
|
14
|
-
|
|
15
|
-
Methods:
|
|
16
|
-
summary(data_group="base"): Returns a summary of the Processing Set as a Pandas table.
|
|
17
|
-
get_ps_max_dims(): Returns the maximum dimension of all the MSs in the Processing Set.
|
|
18
|
-
get_ps_freq_axis(): Combines the frequency axis of all MSs.
|
|
19
|
-
sel(query:str=None, **kwargs): Selects a subset of the Processing Set based on column names and values or a Pandas query.
|
|
20
|
-
ms_sel(**kwargs): Selects a subset of the Processing Set by applying the `sel` method to each individual MS.
|
|
21
|
-
ms_isel(**kwargs): Selects a subset of the Processing Set by applying the `isel` method to each individual MS.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, *args, **kwargs):
|
|
25
|
-
super().__init__(*args, **kwargs)
|
|
26
|
-
self.meta = {"summary": {}}
|
|
27
|
-
|
|
28
|
-
def summary(self, data_group="base"):
|
|
29
|
-
"""
|
|
30
|
-
Returns a summary of the Processing Set as a Pandas table.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
data_group (str): The data group to summarize. Default is "base".
|
|
34
|
-
|
|
35
|
-
Returns:
|
|
36
|
-
pandas.DataFrame: A DataFrame containing the summary information.
|
|
37
|
-
"""
|
|
38
|
-
if data_group in self.meta["summary"]:
|
|
39
|
-
return self.meta["summary"][data_group]
|
|
40
|
-
else:
|
|
41
|
-
self.meta["summary"][data_group] = self._summary(data_group).sort_values(
|
|
42
|
-
by=["name"], ascending=True
|
|
43
|
-
)
|
|
44
|
-
return self.meta["summary"][data_group]
|
|
45
|
-
|
|
46
|
-
def get_ps_max_dims(self):
|
|
47
|
-
"""
|
|
48
|
-
Returns the maximum dimension of all the MSs in the Processing Set.
|
|
49
|
-
|
|
50
|
-
For example, if the Processing Set contains two MSs with dimensions (50, 20, 30) and (10, 30, 40), the maximum dimensions will be (50, 30, 40).
|
|
51
|
-
|
|
52
|
-
Returns:
|
|
53
|
-
dict: A dictionary containing the maximum dimensions of the Processing Set.
|
|
54
|
-
"""
|
|
55
|
-
if "max_dims" in self.meta:
|
|
56
|
-
return self.meta["max_dims"]
|
|
57
|
-
else:
|
|
58
|
-
self.meta["max_dims"] = self._get_ps_max_dims()
|
|
59
|
-
return self.meta["max_dims"]
|
|
60
|
-
|
|
61
|
-
def get_ps_freq_axis(self):
|
|
62
|
-
"""
|
|
63
|
-
Combines the frequency axis of all MSs.
|
|
64
|
-
|
|
65
|
-
Returns:
|
|
66
|
-
xarray.DataArray: The frequency axis of the Processing Set.
|
|
67
|
-
"""
|
|
68
|
-
if "freq_axis" in self.meta:
|
|
69
|
-
return self.meta["freq_axis"]
|
|
70
|
-
else:
|
|
71
|
-
self.meta["freq_axis"] = self._get_ps_freq_axis()
|
|
72
|
-
return self.meta["freq_axis"]
|
|
73
|
-
|
|
74
|
-
def _summary(self, data_group="base"):
|
|
75
|
-
summary_data = {
|
|
76
|
-
"name": [],
|
|
77
|
-
"obs_mode": [],
|
|
78
|
-
"shape": [],
|
|
79
|
-
"polarization": [],
|
|
80
|
-
"scan_number": [],
|
|
81
|
-
"spw_name": [],
|
|
82
|
-
# "field_id": [],
|
|
83
|
-
"field_name": [],
|
|
84
|
-
# "source_id": [],
|
|
85
|
-
"source_name": [],
|
|
86
|
-
# "num_lines": [],
|
|
87
|
-
"line_name": [],
|
|
88
|
-
"field_coords": [],
|
|
89
|
-
"start_frequency": [],
|
|
90
|
-
"end_frequency": [],
|
|
91
|
-
}
|
|
92
|
-
from astropy.coordinates import SkyCoord
|
|
93
|
-
import astropy.units as u
|
|
94
|
-
|
|
95
|
-
for key, value in self.items():
|
|
96
|
-
summary_data["name"].append(key)
|
|
97
|
-
summary_data["obs_mode"].append(value.attrs["partition_info"]["obs_mode"])
|
|
98
|
-
summary_data["spw_name"].append(
|
|
99
|
-
value.attrs["partition_info"]["spectral_window_name"]
|
|
100
|
-
)
|
|
101
|
-
summary_data["polarization"].append(value.polarization.values)
|
|
102
|
-
summary_data["scan_number"].append(
|
|
103
|
-
value.attrs["partition_info"]["scan_number"]
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
if "visibility" in value.attrs["data_groups"][data_group]:
|
|
107
|
-
data_name = value.attrs["data_groups"][data_group]["visibility"]
|
|
108
|
-
center_name = "FIELD_PHASE_CENTER"
|
|
109
|
-
|
|
110
|
-
if "spectrum" in value.attrs["data_groups"][data_group]:
|
|
111
|
-
data_name = value.attrs["data_groups"][data_group]["spectrum"]
|
|
112
|
-
center_name = "FIELD_REFERENCE_CENTER"
|
|
113
|
-
|
|
114
|
-
summary_data["shape"].append(value[data_name].shape)
|
|
115
|
-
|
|
116
|
-
# summary_data["field_id"].append(value.attrs["partition_info"]["field_id"])
|
|
117
|
-
# summary_data["source_id"].append(value.attrs["partition_info"]["source_id"])
|
|
118
|
-
|
|
119
|
-
summary_data["field_name"].append(
|
|
120
|
-
value.attrs["partition_info"]["field_name"]
|
|
121
|
-
)
|
|
122
|
-
summary_data["source_name"].append(
|
|
123
|
-
value.attrs["partition_info"]["source_name"]
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
summary_data["line_name"].append(value.attrs["partition_info"]["line_name"])
|
|
127
|
-
|
|
128
|
-
# summary_data["num_lines"].append(value.attrs["partition_info"]["num_lines"])
|
|
129
|
-
summary_data["start_frequency"].append(
|
|
130
|
-
to_list(value["frequency"].values)[0]
|
|
131
|
-
)
|
|
132
|
-
summary_data["end_frequency"].append(to_list(value["frequency"].values)[-1])
|
|
133
|
-
|
|
134
|
-
if value[data_name].attrs["field_and_source_xds"].is_ephemeris:
|
|
135
|
-
summary_data["field_coords"].append("Ephemeris")
|
|
136
|
-
elif (
|
|
137
|
-
"time"
|
|
138
|
-
in value[data_name].attrs["field_and_source_xds"][center_name].coords
|
|
139
|
-
):
|
|
140
|
-
summary_data["field_coords"].append("Multi-Phase-Center")
|
|
141
|
-
else:
|
|
142
|
-
ra_dec_rad = (
|
|
143
|
-
value[data_name].attrs["field_and_source_xds"][center_name].values
|
|
144
|
-
)
|
|
145
|
-
frame = (
|
|
146
|
-
value[data_name]
|
|
147
|
-
.attrs["field_and_source_xds"][center_name]
|
|
148
|
-
.attrs["frame"]
|
|
149
|
-
.lower()
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
coord = SkyCoord(
|
|
153
|
-
ra=ra_dec_rad[0] * u.rad, dec=ra_dec_rad[1] * u.rad, frame=frame
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
summary_data["field_coords"].append(
|
|
157
|
-
[
|
|
158
|
-
frame,
|
|
159
|
-
coord.ra.to_string(unit=u.hour, precision=2),
|
|
160
|
-
coord.dec.to_string(unit=u.deg, precision=2),
|
|
161
|
-
]
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
summary_df = pd.DataFrame(summary_data)
|
|
165
|
-
return summary_df
|
|
166
|
-
|
|
167
|
-
def _get_ps_freq_axis(self):
|
|
168
|
-
import xarray as xr
|
|
169
|
-
|
|
170
|
-
spw_ids = []
|
|
171
|
-
freq_axis_list = []
|
|
172
|
-
frame = self.get(0).frequency.attrs["frame"]
|
|
173
|
-
for ms_xds in self.values():
|
|
174
|
-
assert (
|
|
175
|
-
frame == ms_xds.frequency.attrs["frame"]
|
|
176
|
-
), "Frequency reference frame not consistent in Processing Set."
|
|
177
|
-
if ms_xds.frequency.attrs["spectral_window_id"] not in spw_ids:
|
|
178
|
-
spw_ids.append(ms_xds.frequency.attrs["spectral_window_id"])
|
|
179
|
-
freq_axis_list.append(ms_xds.frequency)
|
|
180
|
-
|
|
181
|
-
freq_axis = xr.concat(freq_axis_list, dim="frequency").sortby("frequency")
|
|
182
|
-
return freq_axis
|
|
183
|
-
|
|
184
|
-
def _get_ps_max_dims(self):
|
|
185
|
-
max_dims = None
|
|
186
|
-
for ms_xds in self.values():
|
|
187
|
-
if max_dims is None:
|
|
188
|
-
max_dims = dict(ms_xds.sizes)
|
|
189
|
-
else:
|
|
190
|
-
for dim_name, size in ms_xds.sizes.items():
|
|
191
|
-
if dim_name in max_dims:
|
|
192
|
-
if max_dims[dim_name] < size:
|
|
193
|
-
max_dims[dim_name] = size
|
|
194
|
-
else:
|
|
195
|
-
max_dims[dim_name] = size
|
|
196
|
-
return max_dims
|
|
197
|
-
|
|
198
|
-
def get(self, id):
|
|
199
|
-
return self[list(self.keys())[id]]
|
|
200
|
-
|
|
201
|
-
def sel(self, string_exact_match: bool = True, query: str = None, **kwargs):
|
|
202
|
-
"""
|
|
203
|
-
Selects a subset of the Processing Set based on column names and values or a Pandas query.
|
|
204
|
-
|
|
205
|
-
The following columns are supported: name, obs_mode, polarization, spw_name, field_name, source_name, field_coords, start_frequency, end_frequency.
|
|
206
|
-
|
|
207
|
-
This function will not apply any selection on the MS data so data will not be dropped for example if a MS has field_name=['field_0','field_10','field_08'] and ps.sel(field_name='field_0') is done the resulting MS will still have field_name=['field_0','field_10','field_08'].
|
|
208
|
-
|
|
209
|
-
Examples:
|
|
210
|
-
ps.sel(obs_mode='OBSERVE_TARGET#ON_SOURCE', polarization=['RR', 'LL']) # Select all MSs with obs_mode 'OBSERVE_TARGET#ON_SOURCE' and polarization 'RR' or 'LL'.
|
|
211
|
-
ps.sel(query='start_frequency > 100e9 AND end_frequency < 200e9') # Select all MSs with start_frequency greater than 100 GHz and less than 200 GHz.
|
|
212
|
-
|
|
213
|
-
Args:
|
|
214
|
-
query (str): A Pandas query string. Default is None.
|
|
215
|
-
string_exact_match (bool): If True, the selection will be an exact match for string and string list columns. Default is True.
|
|
216
|
-
**kwargs: Keyword arguments representing column names and values to filter the Processing Set.
|
|
217
|
-
|
|
218
|
-
Returns:
|
|
219
|
-
processing_set: The subset of the Processing Set.
|
|
220
|
-
"""
|
|
221
|
-
import numpy as np
|
|
222
|
-
|
|
223
|
-
# def select_rows(df, col, input_strings):
|
|
224
|
-
# return df[df[col].apply(lambda x: any(i in x for i in input_strings))]
|
|
225
|
-
|
|
226
|
-
# def select_rows(df, col, sel, string_exact_match):
|
|
227
|
-
# def check_selection(row_val):
|
|
228
|
-
# if isinstance(row_val, numbers.Number) or string_exact_match:
|
|
229
|
-
# return any(i == row_val for i in sel) #If values are numbers
|
|
230
|
-
# return any(i in row_val for i in sel) #If values are strings
|
|
231
|
-
# return df[df[col].apply(check_selection)]
|
|
232
|
-
|
|
233
|
-
def select_rows(df, col, sel_vals, string_exact_match):
|
|
234
|
-
def check_selection(row_val):
|
|
235
|
-
row_val = to_list(
|
|
236
|
-
row_val
|
|
237
|
-
) # make sure that it is a list so that we can iterate over it.
|
|
238
|
-
|
|
239
|
-
for rw in row_val:
|
|
240
|
-
for s in sel_vals:
|
|
241
|
-
if string_exact_match:
|
|
242
|
-
if rw == s:
|
|
243
|
-
return True
|
|
244
|
-
else:
|
|
245
|
-
if s in rw:
|
|
246
|
-
return True
|
|
247
|
-
return False
|
|
248
|
-
|
|
249
|
-
return df[df[col].apply(check_selection)]
|
|
250
|
-
|
|
251
|
-
summary_table = self.summary()
|
|
252
|
-
for key, value in kwargs.items():
|
|
253
|
-
value = to_list(value) # make sure value is a list.
|
|
254
|
-
|
|
255
|
-
if len(value) == 1 and isinstance(value[0], slice):
|
|
256
|
-
summary_table = summary_table[
|
|
257
|
-
summary_table[key].between(value[0].start, value[0].stop)
|
|
258
|
-
]
|
|
259
|
-
else:
|
|
260
|
-
summary_table = select_rows(
|
|
261
|
-
summary_table, key, value, string_exact_match
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
if query is not None:
|
|
265
|
-
summary_table = summary_table.query(query)
|
|
266
|
-
|
|
267
|
-
sub_ps = processing_set()
|
|
268
|
-
for key, val in self.items():
|
|
269
|
-
if key in summary_table["name"].values:
|
|
270
|
-
sub_ps[key] = val
|
|
271
|
-
|
|
272
|
-
return sub_ps
|
|
273
|
-
|
|
274
|
-
def ms_sel(self, **kwargs):
|
|
275
|
-
"""
|
|
276
|
-
Selects a subset of the Processing Set by applying the `sel` method to each MS.
|
|
277
|
-
|
|
278
|
-
Args:
|
|
279
|
-
**kwargs: Keyword arguments representing column names and values to filter the Processing Set.
|
|
280
|
-
|
|
281
|
-
Returns:
|
|
282
|
-
processing_set: The subset of the Processing Set.
|
|
283
|
-
"""
|
|
284
|
-
sub_ps = processing_set()
|
|
285
|
-
for key, val in self.items():
|
|
286
|
-
sub_ps[key] = val.sel(kwargs)
|
|
287
|
-
return sub_ps
|
|
288
|
-
|
|
289
|
-
def ms_isel(self, **kwargs):
|
|
290
|
-
"""
|
|
291
|
-
Selects a subset of the Processing Set by applying the `isel` method to each MS.
|
|
292
|
-
|
|
293
|
-
Args:
|
|
294
|
-
**kwargs: Keyword arguments representing dimension names and indices to select from the Processing Set.
|
|
295
|
-
|
|
296
|
-
Returns:
|
|
297
|
-
processing_set: The subset of the Processing Set.
|
|
298
|
-
"""
|
|
299
|
-
sub_ps = processing_set()
|
|
300
|
-
for key, val in self.items():
|
|
301
|
-
sub_ps[key] = val.isel(kwargs)
|
|
302
|
-
return sub_ps
|