xradio 0.0.28__py3-none-any.whl → 0.0.30__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 +5 -4
- xradio/_utils/array.py +90 -0
- xradio/_utils/zarr/common.py +48 -3
- xradio/image/_util/zarr.py +4 -1
- xradio/schema/__init__.py +24 -6
- xradio/schema/bases.py +440 -2
- xradio/schema/check.py +96 -55
- xradio/schema/dataclass.py +123 -27
- xradio/schema/metamodel.py +21 -4
- xradio/schema/typing.py +33 -18
- xradio/vis/__init__.py +5 -2
- xradio/vis/_processing_set.py +71 -32
- xradio/vis/_vis_utils/_ms/_tables/create_field_and_source_xds.py +710 -0
- xradio/vis/_vis_utils/_ms/_tables/load.py +23 -10
- xradio/vis/_vis_utils/_ms/_tables/load_main_table.py +145 -64
- xradio/vis/_vis_utils/_ms/_tables/read.py +747 -172
- xradio/vis/_vis_utils/_ms/_tables/read_main_table.py +173 -44
- xradio/vis/_vis_utils/_ms/_tables/read_subtables.py +79 -28
- xradio/vis/_vis_utils/_ms/_tables/write.py +102 -45
- xradio/vis/_vis_utils/_ms/_tables/write_exp_api.py +127 -65
- xradio/vis/_vis_utils/_ms/chunks.py +58 -21
- xradio/vis/_vis_utils/_ms/conversion.py +582 -102
- xradio/vis/_vis_utils/_ms/descr.py +52 -20
- xradio/vis/_vis_utils/_ms/msv2_to_msv4_meta.py +72 -35
- xradio/vis/_vis_utils/_ms/msv4_infos.py +0 -59
- xradio/vis/_vis_utils/_ms/msv4_sub_xdss.py +76 -9
- xradio/vis/_vis_utils/_ms/optimised_functions.py +0 -46
- xradio/vis/_vis_utils/_ms/partition_queries.py +308 -119
- xradio/vis/_vis_utils/_ms/partitions.py +82 -25
- xradio/vis/_vis_utils/_ms/subtables.py +32 -14
- xradio/vis/_vis_utils/_utils/partition_attrs.py +30 -11
- xradio/vis/_vis_utils/_utils/xds_helper.py +136 -45
- xradio/vis/_vis_utils/_zarr/read.py +60 -22
- xradio/vis/_vis_utils/_zarr/write.py +83 -9
- xradio/vis/_vis_utils/ms.py +48 -29
- xradio/vis/_vis_utils/zarr.py +44 -20
- xradio/vis/convert_msv2_to_processing_set.py +43 -32
- xradio/vis/load_processing_set.py +38 -61
- xradio/vis/read_processing_set.py +64 -96
- xradio/vis/schema.py +687 -0
- xradio/vis/vis_io.py +75 -43
- {xradio-0.0.28.dist-info → xradio-0.0.30.dist-info}/LICENSE.txt +6 -1
- {xradio-0.0.28.dist-info → xradio-0.0.30.dist-info}/METADATA +10 -5
- xradio-0.0.30.dist-info/RECORD +73 -0
- {xradio-0.0.28.dist-info → xradio-0.0.30.dist-info}/WHEEL +1 -1
- xradio/vis/model.py +0 -497
- xradio-0.0.28.dist-info/RECORD +0 -71
- {xradio-0.0.28.dist-info → xradio-0.0.30.dist-info}/top_level.txt +0 -0
xradio/vis/schema.py
ADDED
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Literal, Optional, Union, List
|
|
4
|
+
from xradio.schema.bases import (
|
|
5
|
+
xarray_dataset_schema,
|
|
6
|
+
xarray_dataarray_schema,
|
|
7
|
+
dict_schema,
|
|
8
|
+
)
|
|
9
|
+
from xradio.schema.typing import Attr, Coord, Coordof, Data, Dataof, Name
|
|
10
|
+
import numpy
|
|
11
|
+
|
|
12
|
+
# Dimensions
|
|
13
|
+
Time = Literal["time"]
|
|
14
|
+
""" Observation time dimension """
|
|
15
|
+
AntennaId = Literal["antenna_id"]
|
|
16
|
+
""" Antenna ID dimension """
|
|
17
|
+
ReceptorName = Literal["receptor_name"]
|
|
18
|
+
""" Receptor name dimension """
|
|
19
|
+
BaselineId = Literal["baseline_id"]
|
|
20
|
+
""" Baseline ID dimension """
|
|
21
|
+
Frequency = Literal["frequency"]
|
|
22
|
+
""" Frequency dimension """
|
|
23
|
+
Polarization = Literal["polarization"]
|
|
24
|
+
""" Polarization dimension """
|
|
25
|
+
UvwLabel = Literal["uvw_label"]
|
|
26
|
+
""" Coordinate dimension of UVW data (typically shape 3 for 'u', 'v', 'w') """
|
|
27
|
+
XyzLabel = Literal["xyz_label"]
|
|
28
|
+
""" Coordinate dimension of earth location data (typically shape 3 and 'x', 'y', 'z')"""
|
|
29
|
+
TimePolynomial = Literal["time_polynomial"]
|
|
30
|
+
""" For data that is represented as variable in time using Taylor expansion """
|
|
31
|
+
SkyCoordLabel = Literal["sky_coord_label"]
|
|
32
|
+
""" Unlabeled axis """
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Plain data class models
|
|
36
|
+
@dict_schema
|
|
37
|
+
class SourceInfoDict:
|
|
38
|
+
# TODO
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@xarray_dataarray_schema
|
|
43
|
+
class TimeArray:
|
|
44
|
+
data: Data[Time, float]
|
|
45
|
+
|
|
46
|
+
scale: Attr[str] = "tai"
|
|
47
|
+
"""Astropy time scales."""
|
|
48
|
+
format: Attr[str] = "unix"
|
|
49
|
+
"""Seconds from 1970-01-01 00:00:00 UTC"""
|
|
50
|
+
|
|
51
|
+
type: Attr[str] = "time"
|
|
52
|
+
units: Attr[list] = ("s",)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@xarray_dataarray_schema
|
|
56
|
+
class SkyCoordArray:
|
|
57
|
+
data: Data[SkyCoordLabel, float]
|
|
58
|
+
|
|
59
|
+
type: Attr[str] = "sky_coord"
|
|
60
|
+
units: Attr[list] = ("rad", "rad")
|
|
61
|
+
frame: Attr[str] = ""
|
|
62
|
+
"""
|
|
63
|
+
From fixvis docs: clean and the im tool ignore the reference frame
|
|
64
|
+
claimed by the UVW column (it is often mislabelled as ITRF when it is
|
|
65
|
+
really FK5 (J2000)) and instead assume the (u, v, w)s are in the same frame
|
|
66
|
+
as the phase tracking center. calcuvw does not yet force the UVW column and
|
|
67
|
+
field centers to use the same reference frame! Blank = use the phase
|
|
68
|
+
tracking frame of vis.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dict_schema
|
|
73
|
+
class FieldInfoDict:
|
|
74
|
+
"""
|
|
75
|
+
Field positions for each source.
|
|
76
|
+
|
|
77
|
+
Defines a field position on the sky. For interferometers, this is the correlated field position.
|
|
78
|
+
For single dishes, this is the nominal pointing direction.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
name: str
|
|
82
|
+
"""Field name."""
|
|
83
|
+
field_id: int
|
|
84
|
+
"""Field id"""
|
|
85
|
+
code: str
|
|
86
|
+
"""Field code indicating special characteristics of the field; user specified."""
|
|
87
|
+
time_reference: Optional[TimeArray]
|
|
88
|
+
"""
|
|
89
|
+
Time reference for the directions and rates. When used in :py:class:`VisibilityXds` should match
|
|
90
|
+
the scale and format given for ``time`` (see :py:class:`TimeArray`).
|
|
91
|
+
"""
|
|
92
|
+
delay_direction: SkyCoordArray
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@xarray_dataarray_schema
|
|
96
|
+
class QuantityArray:
|
|
97
|
+
"""
|
|
98
|
+
Anonymous quantity
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
data: Data[tuple[()], float]
|
|
102
|
+
|
|
103
|
+
type: Attr[str]
|
|
104
|
+
units: Attr[list]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@xarray_dataarray_schema
|
|
108
|
+
class SpectralCoordArray:
|
|
109
|
+
data: Data[tuple[()], float]
|
|
110
|
+
|
|
111
|
+
frame: Attr[str] = "gcrs"
|
|
112
|
+
"""Astropy time scales."""
|
|
113
|
+
|
|
114
|
+
type: Attr[str] = "frequency"
|
|
115
|
+
units: Attr[list] = ("Hz",)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@xarray_dataarray_schema
|
|
119
|
+
class EarthLocationArray:
|
|
120
|
+
data: Data[XyzLabel, float]
|
|
121
|
+
|
|
122
|
+
ellipsoid: Attr[str]
|
|
123
|
+
"""
|
|
124
|
+
ITRF makes use of GRS80 ellipsoid and WGS84 makes use of WGS84 ellipsoid
|
|
125
|
+
"""
|
|
126
|
+
units: Attr[list] = ("m", "m", "m")
|
|
127
|
+
"""
|
|
128
|
+
If the units are a list of strings then it must be the same length as
|
|
129
|
+
the last dimension of the data array. This allows for having different
|
|
130
|
+
units in the same data array,for example geodetic coordinates could use
|
|
131
|
+
``['rad','rad','m']``.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@dict_schema
|
|
136
|
+
class ObservationInfoDict:
|
|
137
|
+
observer: List[str]
|
|
138
|
+
"""List of observer names."""
|
|
139
|
+
project: str
|
|
140
|
+
"""Project Code/Project_UID"""
|
|
141
|
+
release_data: str
|
|
142
|
+
"""Project release date. This is the date on which the data may become
|
|
143
|
+
public. Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
|
|
144
|
+
execution_block_id: Optional[str]
|
|
145
|
+
""" ASDM: Indicates the position of the execution block in the project
|
|
146
|
+
(sequential numbering starting at 1). """
|
|
147
|
+
execution_block_number: Optional[str]
|
|
148
|
+
"""ASDM: Indicates the position of the execution block in the project
|
|
149
|
+
(sequential numbering starting at 1)."""
|
|
150
|
+
execution_block_UID: Optional[str]
|
|
151
|
+
"""ASDM: The archive’s UID of the execution block."""
|
|
152
|
+
session_reference: Optional[str]
|
|
153
|
+
"""ASDM: The observing session reference."""
|
|
154
|
+
observing_script: Optional[str]
|
|
155
|
+
"""ASDM: The text of the observation script."""
|
|
156
|
+
observing_script_UID: Optional[str]
|
|
157
|
+
"""ASDM: A reference to the Entity which contains the observing script."""
|
|
158
|
+
observing_log: Optional[str]
|
|
159
|
+
"""ASDM: Logs of the observation during this execu- tion block."""
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@dict_schema
|
|
163
|
+
class ProcessorInfoDict:
|
|
164
|
+
type: str
|
|
165
|
+
"""Processor type; reserved keywords include (”CORRELATOR” -
|
|
166
|
+
interferometric correlator; ”SPECTROMETER” - single-dish correlator;
|
|
167
|
+
”RADIOMETER” - generic detector/integrator)."""
|
|
168
|
+
sub_type: str
|
|
169
|
+
"""Processor sub-type, e.g. ”GBT” or ”JIVE”."""
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
# Coordinates / Axes
|
|
173
|
+
@xarray_dataarray_schema
|
|
174
|
+
class TimeArray:
|
|
175
|
+
"""Data model of time axis"""
|
|
176
|
+
|
|
177
|
+
data: Data[Time, float]
|
|
178
|
+
""" Time, expressed in SI seconds since the epoch (see ``scale`` & ``format``). """
|
|
179
|
+
|
|
180
|
+
integration_time: Attr[Optional[TimeArray]] = None
|
|
181
|
+
""" The nominal sampling interval (ms v2). Units of seconds. """
|
|
182
|
+
effective_integration_time: Attr[Optional[TimeArray]] = None
|
|
183
|
+
""" Name of data array that contains the integration time that includes the effects of missing data. """
|
|
184
|
+
|
|
185
|
+
type: Attr[str] = "time"
|
|
186
|
+
""" Coordinate type. Should be ``"time"``. """
|
|
187
|
+
units: Attr[list[str]] = ("s",)
|
|
188
|
+
""" Units to associate with axis"""
|
|
189
|
+
scale: Attr[str] = "tai"
|
|
190
|
+
""" Astropy time scales, see :py:class:`astropy.time.Time` """
|
|
191
|
+
format: Attr[str] = "unix"
|
|
192
|
+
""" Astropy format, see :py:class:`astropy.time.Time`. Default seconds from 1970-01-01 00:00:00 UTC """
|
|
193
|
+
long_name: Optional[Attr[str]] = "Observation Time"
|
|
194
|
+
""" Long-form name to use for axis"""
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@xarray_dataarray_schema
|
|
198
|
+
class AntennaArray:
|
|
199
|
+
data: Data[AntennaId, int]
|
|
200
|
+
"""
|
|
201
|
+
Antenna id of an antenna. Maps to ``antenna_id``
|
|
202
|
+
in :py:class:`AntennaXds`.
|
|
203
|
+
"""
|
|
204
|
+
long_name: Optional[Attr[str]] = "Antenna ID"
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@xarray_dataarray_schema
|
|
208
|
+
class BaselineArray:
|
|
209
|
+
"""TODO: documentation"""
|
|
210
|
+
|
|
211
|
+
data: Data[BaselineId, Union[numpy.int64, numpy.int32]]
|
|
212
|
+
"""Unique id for each baseline."""
|
|
213
|
+
long_name: Optional[Attr[str]] = "Baseline ID"
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@xarray_dataarray_schema
|
|
217
|
+
class BaselineAntennaArray:
|
|
218
|
+
data: Data[BaselineId, Union[numpy.int64, numpy.int32]]
|
|
219
|
+
"""
|
|
220
|
+
Antenna id for an antenna in a baseline. Maps to ``attrs['antenna_xds'].antenna_id``
|
|
221
|
+
in :py:class:`VisibilityXds`
|
|
222
|
+
"""
|
|
223
|
+
long_name: Optional[Attr[str]] = "Baseline Antenna ID"
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@xarray_dataset_schema
|
|
227
|
+
class DopplerXds:
|
|
228
|
+
# TODO
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@xarray_dataarray_schema
|
|
233
|
+
class FrequencyArray:
|
|
234
|
+
"""TODO: documentation"""
|
|
235
|
+
|
|
236
|
+
data: Data[Frequency, float]
|
|
237
|
+
""" Time, expressed in SI seconds since the epoch. """
|
|
238
|
+
spectral_window_name: Attr[str]
|
|
239
|
+
""" Name associated with spectral window. """
|
|
240
|
+
frequency_group_name: Attr[str]
|
|
241
|
+
""" Name associated with frequency group - needed for multi-band VLBI fringe-fitting."""
|
|
242
|
+
reference_frequency: Attr[SpectralCoordArray]
|
|
243
|
+
""" A frequency representative of the spectral window, usually the sky
|
|
244
|
+
frequency corresponding to the DC edge of the baseband. Used by the calibration
|
|
245
|
+
system if a fixed scaling frequency is required or in algorithms to identify the
|
|
246
|
+
observing band. """
|
|
247
|
+
channel_width: Attr[SpectralCoordArray]
|
|
248
|
+
""" The nominal channel bandwidth. Same units as data array (see units key). """
|
|
249
|
+
doppler: Optional[Attr[DopplerXds]]
|
|
250
|
+
""" Doppler tracking information """
|
|
251
|
+
|
|
252
|
+
type: Attr[str] = "spectral_coord"
|
|
253
|
+
""" Coordinate type. Should be ``"spectral_coord"``. """
|
|
254
|
+
long_name: Optional[Attr[str]] = "Frequency"
|
|
255
|
+
""" Long-form name to use for axis"""
|
|
256
|
+
units: Attr[list[str]] = ("Hz",)
|
|
257
|
+
""" Units to associate with axis"""
|
|
258
|
+
frame: Attr[str] = "icrs"
|
|
259
|
+
"""
|
|
260
|
+
Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
|
|
261
|
+
Note that Astropy does not use the name
|
|
262
|
+
'topo' (telescope centric) velocity frame, rather it assumes if no velocity
|
|
263
|
+
frame is given that this is the default.
|
|
264
|
+
"""
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@xarray_dataarray_schema
|
|
268
|
+
class PolarizationArray:
|
|
269
|
+
"""
|
|
270
|
+
Possible correlations that can be formed from polarised receptors. Possible
|
|
271
|
+
values, taken from `Measures/Stokes.h
|
|
272
|
+
<https://github.com/casacore/casacore/blob/5a8df94738bdc36be27e695d7b14fe949a1cc2df/measures/Measures/Stokes.h>`_:
|
|
273
|
+
|
|
274
|
+
* ``I``, ``Q``, ``U``, ``V`` (standard stokes parameters)
|
|
275
|
+
* ``RR``, ``RL``, ``LR``, ``LL`` (circular correlation products)
|
|
276
|
+
* ``XX``, ``XY``, ``YX``, ``YY`` (linear correlation products)
|
|
277
|
+
* ``RX``, ``RY``, ``LX``, ``LY``, ``XR``, ``XL``, ``YR``, ``YL`` (mixed correlation products)
|
|
278
|
+
* ``PP``, ``PQ``, ``QP``, ``QQ`` (general quasi-orthogonal correlation products)
|
|
279
|
+
* ``RCircular``, ``LCircular``, ``Linear`` (single dish polarization types)
|
|
280
|
+
* ``Ptotal`` (polarized intensity: ``sqrt(Q²+U²+V²)``)
|
|
281
|
+
* ``Plinear`` (linearly polarized intensity: ``sqrt(Q²+U²)``)
|
|
282
|
+
* ``PFtotal`` (polarization fraction: ``Ptotal/I``)
|
|
283
|
+
* ``PFlinear`` (linear polarization fraction: ``Plinear/I``)
|
|
284
|
+
* ``Pangle`` (linear polarization angle: ``0.5 arctan(U/Q)`` in radians)
|
|
285
|
+
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
data: Data[Polarization, str]
|
|
289
|
+
""" Polarization names. """
|
|
290
|
+
long_name: Optional[Attr[str]] = "Polarization"
|
|
291
|
+
""" Long-form name to use for axis. Should be ``"Polarization"``"""
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
@xarray_dataarray_schema
|
|
295
|
+
class UvwLabelArray:
|
|
296
|
+
"""
|
|
297
|
+
Coordinate axis to make up ``("u", "v", "w")`` tuple, see :py:class:`UvwArray`.
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
data: Data[UvwLabel, str] = ("u", "v", "w")
|
|
301
|
+
"""Should be ``('u','v','w')``, used by :py:class:`UvwArray`"""
|
|
302
|
+
long_name: Optional[Attr[str]] = "U/V/W label"
|
|
303
|
+
""" Long-form name to use for axis. Should be ``"U/V/W label"``"""
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
# Data variables
|
|
307
|
+
@xarray_dataarray_schema
|
|
308
|
+
class VisibilityArray:
|
|
309
|
+
"""TODO: documentation"""
|
|
310
|
+
|
|
311
|
+
data: Data[
|
|
312
|
+
tuple[Time, BaselineId, Frequency, Polarization],
|
|
313
|
+
Union[numpy.complex64, numpy.complex128],
|
|
314
|
+
]
|
|
315
|
+
time: Coord[tuple[()], TimeArray]
|
|
316
|
+
baseline_id: Coord[tuple[()], BaselineArray]
|
|
317
|
+
frequency: Coord[tuple[()], FrequencyArray]
|
|
318
|
+
polarization: Coord[tuple[()], PolarizationArray]
|
|
319
|
+
field_info: Attr[FieldInfoDict]
|
|
320
|
+
long_name: Optional[Attr[str]] = "Visibility values"
|
|
321
|
+
""" Long-form name to use for axis. Should be ``"Visibility values"``"""
|
|
322
|
+
units: Attr[list] = ("Jy",)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
@xarray_dataarray_schema
|
|
326
|
+
class FlagArray:
|
|
327
|
+
"""
|
|
328
|
+
An array of Boolean values with the same shape as `VISIBILITY`,
|
|
329
|
+
representing the cumulative flags applying to this data matrix. Data are
|
|
330
|
+
flagged bad if the ``FLAG`` array element is ``True``.
|
|
331
|
+
"""
|
|
332
|
+
|
|
333
|
+
data: Data[
|
|
334
|
+
Union[
|
|
335
|
+
tuple[Time, BaselineId, Frequency, Polarization],
|
|
336
|
+
tuple[Time, BaselineId, Frequency],
|
|
337
|
+
tuple[Time, BaselineId],
|
|
338
|
+
],
|
|
339
|
+
bool,
|
|
340
|
+
]
|
|
341
|
+
time: Coordof[TimeArray]
|
|
342
|
+
baseline_id: Coordof[BaselineArray]
|
|
343
|
+
frequency: Coordof[FrequencyArray]
|
|
344
|
+
polarization: Optional[Coordof[PolarizationArray]] = None
|
|
345
|
+
long_name: Optional[Attr[str]] = "Visibility flags"
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
@xarray_dataarray_schema
|
|
349
|
+
class WeightArray:
|
|
350
|
+
"""
|
|
351
|
+
The weight for each channel, with the same shape as the associated
|
|
352
|
+
:py:class:`VisibilityArray`, as assigned by the correlator or processor.
|
|
353
|
+
|
|
354
|
+
Weight spectrum in ms v2 is renamed weight. Should be calculated as
|
|
355
|
+
1/sigma^2 (sigma rms noise).
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
data: Data[
|
|
359
|
+
Union[
|
|
360
|
+
tuple[Time, BaselineId, Frequency, Polarization],
|
|
361
|
+
tuple[Time, BaselineId, Frequency],
|
|
362
|
+
tuple[Time, BaselineId],
|
|
363
|
+
],
|
|
364
|
+
Union[numpy.float16, numpy.float32, numpy.float64],
|
|
365
|
+
]
|
|
366
|
+
"""Visibility weights"""
|
|
367
|
+
time: Coordof[TimeArray]
|
|
368
|
+
baseline_id: Coordof[BaselineArray]
|
|
369
|
+
frequency: Optional[Coordof[FrequencyArray]] = None
|
|
370
|
+
polarization: Optional[Coordof[PolarizationArray]] = None
|
|
371
|
+
long_name: Optional[Attr[str]] = "Visibility weights"
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
@xarray_dataarray_schema
|
|
375
|
+
class UvwArray:
|
|
376
|
+
"""
|
|
377
|
+
Coordinates for the baseline from ``baseline_antenna2_id`` to
|
|
378
|
+
``baseline_antenna1_id``, i.e. the baseline is equal to the difference
|
|
379
|
+
``POSITION2 - POSITION1``. The UVW given are for the ``TIME_CENTROID``, and
|
|
380
|
+
correspond in general to the reference type for the
|
|
381
|
+
``field_info.phase_dir``.
|
|
382
|
+
|
|
383
|
+
The baseline direction should be: ``W`` towards source direction; ``V`` in
|
|
384
|
+
plane through source and system's pole; ``U`` in direction of increasing
|
|
385
|
+
longitude coordinate. So citing
|
|
386
|
+
http://casa.nrao.edu/Memos/CoordConvention.pdf: Consider an XYZ Celestial
|
|
387
|
+
coordinate system centered at the location of the interferometer, with
|
|
388
|
+
:math:`X` towards the East, :math:`Z` towards the NCP and :math:`Y` to
|
|
389
|
+
complete a right-handed system. The UVW coordinate system is then defined
|
|
390
|
+
by the hour-angle and declination of the phase-reference direction such
|
|
391
|
+
that
|
|
392
|
+
|
|
393
|
+
#. when the direction of observation is the NCP (`ha=0,dec=90`),
|
|
394
|
+
the UVW coordinates are aligned with XYZ,
|
|
395
|
+
#. V, W and the NCP are always on a Great circle,
|
|
396
|
+
#. when W is on the local meridian, U points East
|
|
397
|
+
#. when the direction of observation is at zero declination, an
|
|
398
|
+
hour-angle of -6 hours makes W point due East.
|
|
399
|
+
|
|
400
|
+
This definition also determines the sign of the phase of ``VISIBILITY``.
|
|
401
|
+
|
|
402
|
+
"""
|
|
403
|
+
|
|
404
|
+
data: Data[
|
|
405
|
+
Union[
|
|
406
|
+
tuple[Time, BaselineId, Frequency, Polarization, UvwLabel],
|
|
407
|
+
tuple[Time, BaselineId, Frequency, UvwLabel],
|
|
408
|
+
tuple[Time, BaselineId, UvwLabel],
|
|
409
|
+
],
|
|
410
|
+
Union[
|
|
411
|
+
numpy.float16,
|
|
412
|
+
numpy.float32,
|
|
413
|
+
numpy.float64,
|
|
414
|
+
],
|
|
415
|
+
]
|
|
416
|
+
"""Baseline coordinates from ``baseline_antenna2_id`` to ``baseline_antenna1_id``"""
|
|
417
|
+
time: Coordof[TimeArray]
|
|
418
|
+
baseline_id: Coordof[BaselineArray]
|
|
419
|
+
frequency: Optional[Coordof[FrequencyArray]] = None
|
|
420
|
+
polarization: Optional[Coordof[PolarizationArray]] = None
|
|
421
|
+
uvw_label: Coordof[UvwLabelArray] = ("u", "v", "w")
|
|
422
|
+
long_name: Optional[Attr[str]] = "Baseline coordinates"
|
|
423
|
+
""" Long-form name to use for axis. Should be ``"Baseline coordinates``"""
|
|
424
|
+
units: Attr[list[str]] = ("m",)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
@xarray_dataarray_schema
|
|
428
|
+
class TimeSamplingArray:
|
|
429
|
+
"""TODO: documentation"""
|
|
430
|
+
|
|
431
|
+
data: Data[
|
|
432
|
+
Union[
|
|
433
|
+
tuple[Time, BaselineId, Frequency, Polarization],
|
|
434
|
+
tuple[Time, BaselineId, Frequency],
|
|
435
|
+
tuple[Time, BaselineId],
|
|
436
|
+
],
|
|
437
|
+
float,
|
|
438
|
+
]
|
|
439
|
+
|
|
440
|
+
time: Coordof[TimeArray]
|
|
441
|
+
baseline_id: Coordof[BaselineArray]
|
|
442
|
+
frequency: Optional[Coordof[FrequencyArray]] = None
|
|
443
|
+
polarization: Optional[Coordof[PolarizationArray]] = None
|
|
444
|
+
|
|
445
|
+
scale: Attr[str] = "tai"
|
|
446
|
+
""" Astropy time scales, see :py:class:`astropy.time.Time` """
|
|
447
|
+
format: Attr[str] = "unix"
|
|
448
|
+
""" Astropy format, see :py:class:`astropy.time.Time`. Default seconds from 1970-01-01 00:00:00 UTC """
|
|
449
|
+
|
|
450
|
+
long_name: Optional[Attr[str]] = "Time sampling data"
|
|
451
|
+
units: Attr[str] = "s"
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
@xarray_dataarray_schema
|
|
455
|
+
class FreqSamplingArray:
|
|
456
|
+
"""TODO: documentation"""
|
|
457
|
+
|
|
458
|
+
data: Data[
|
|
459
|
+
Union[
|
|
460
|
+
tuple[Time, BaselineId, Frequency, Polarization],
|
|
461
|
+
tuple[Time, BaselineId, Frequency],
|
|
462
|
+
tuple[Time, Frequency],
|
|
463
|
+
tuple[Frequency],
|
|
464
|
+
],
|
|
465
|
+
float,
|
|
466
|
+
]
|
|
467
|
+
"""
|
|
468
|
+
Data about frequency sampling, such as centroid or integration
|
|
469
|
+
time. Concrete function depends on concrete data array within
|
|
470
|
+
:py:class:`VisibilityXds`.
|
|
471
|
+
"""
|
|
472
|
+
frequency: Coordof[FrequencyArray]
|
|
473
|
+
time: Optional[Coordof[TimeArray]] = None
|
|
474
|
+
baseline_id: Optional[Coordof[BaselineArray]] = None
|
|
475
|
+
polarization: Optional[Coordof[PolarizationArray]] = None
|
|
476
|
+
long_name: Optional[Attr[str]] = "Frequency sampling data"
|
|
477
|
+
units: Attr[str] = "Hz"
|
|
478
|
+
frame: Attr[str] = "icrs"
|
|
479
|
+
"""
|
|
480
|
+
Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
|
|
481
|
+
Note that Astropy does not use the name
|
|
482
|
+
'topo' (telescope centric) velocity frame, rather it assumes if no velocity
|
|
483
|
+
frame is given that this is the default.
|
|
484
|
+
"""
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
# Data Sets
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
@xarray_dataset_schema
|
|
491
|
+
class AntennaXds:
|
|
492
|
+
# --- Coordinates ---
|
|
493
|
+
antenna_id: Coordof[AntennaArray]
|
|
494
|
+
"""Antenna ID"""
|
|
495
|
+
name: Coord[AntennaId, str]
|
|
496
|
+
|
|
497
|
+
"""Antenna name."""
|
|
498
|
+
station: Coord[AntennaId, str]
|
|
499
|
+
"""Name of the station pad (relevant to arrays with moving antennas)."""
|
|
500
|
+
antenna_type: Optional[Coord[AntennaId, str]]
|
|
501
|
+
"""Antenna type.
|
|
502
|
+
|
|
503
|
+
Reserved keywords include: (``GROUND-BASED`` - conventional
|
|
504
|
+
antennas; ``SPACE-BASED`` - orbiting antennas; ``TRACKING-STN`` - tracking
|
|
505
|
+
stations)."""
|
|
506
|
+
mount: Coord[AntennaId, str]
|
|
507
|
+
"""Mount type of the antenna.
|
|
508
|
+
|
|
509
|
+
Reserved keywords include: (``EQUATORIAL`` - equatorial mount; ``ALTAZ`` -
|
|
510
|
+
azimuth-elevation mount; ``X-Y`` - x-y mount; ``SPACE-HALCA`` - specific
|
|
511
|
+
orientation model.)"""
|
|
512
|
+
observatory: Optional[Coord[AntennaId, str]]
|
|
513
|
+
"""Support for VLBI"""
|
|
514
|
+
receptor_name: Optional[Coord[ReceptorName, str]]
|
|
515
|
+
"""Names of receptors"""
|
|
516
|
+
xyz_label: Coord[XyzLabel, str]
|
|
517
|
+
"""Coordinate dimension of earth location data (typically shape 3 and 'x', 'y', 'z')"""
|
|
518
|
+
sky_coord_label: Optional[Coord[SkyCoordLabel, str]]
|
|
519
|
+
"""Coordinate dimension of sky coordinate data (possibly shape 2 and 'RA', "Dec")"""
|
|
520
|
+
|
|
521
|
+
# --- Data variables ---
|
|
522
|
+
POSITION: Data[AntennaId, EarthLocationArray]
|
|
523
|
+
"""
|
|
524
|
+
In a right-handed frame, X towards the intersection of the equator and
|
|
525
|
+
the Greenwich meridian, Z towards the pole.
|
|
526
|
+
"""
|
|
527
|
+
FEED_OFFSET: Data[tuple[AntennaId, XyzLabel], QuantityArray]
|
|
528
|
+
"""
|
|
529
|
+
Offset of feed relative to position (``Antenna_Table.offset + Feed_Table.position``).
|
|
530
|
+
"""
|
|
531
|
+
DISH_DIAMETER: Data[AntennaId, QuantityArray]
|
|
532
|
+
"""
|
|
533
|
+
Nominal diameter of dish, as opposed to the effective diameter.
|
|
534
|
+
"""
|
|
535
|
+
BEAM_OFFSET: Optional[Data[AntennaId, SkyCoordArray]]
|
|
536
|
+
"""
|
|
537
|
+
Beam position offset, as defined on the sky but in the antenna
|
|
538
|
+
reference frame.
|
|
539
|
+
"""
|
|
540
|
+
RECEPTOR_ANGLE: Optional[Data[tuple[AntennaId, ReceptorName], QuantityArray]]
|
|
541
|
+
"""
|
|
542
|
+
Polarization reference angle. Converts into parallactic angle in the sky domain.
|
|
543
|
+
"""
|
|
544
|
+
FOCUS_LENGTH: Optional[Data[AntennaId, QuantityArray]]
|
|
545
|
+
"""
|
|
546
|
+
Focus length. As defined along the optical axis of the antenna.
|
|
547
|
+
"""
|
|
548
|
+
ARRAY_CENTER: Optional[Data[AntennaId, EarthLocationArray]]
|
|
549
|
+
EFFECTIVE_DISH_DIAMETER: Optional[Data[AntennaId, QuantityArray]]
|
|
550
|
+
|
|
551
|
+
# --- Attributes ---
|
|
552
|
+
telescope_name: Optional[Attr[str]]
|
|
553
|
+
"""
|
|
554
|
+
From MS v2 observation table
|
|
555
|
+
"""
|
|
556
|
+
type: Attr[str] = "antenna"
|
|
557
|
+
"""
|
|
558
|
+
Type of dataset. Expected to be ``antenna``
|
|
559
|
+
"""
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
@xarray_dataset_schema
|
|
563
|
+
class PointingXds:
|
|
564
|
+
time: Coordof[TimeArray]
|
|
565
|
+
"""
|
|
566
|
+
Mid-point of the time interval for which the information in this row is
|
|
567
|
+
valid. Required to use the same time measure reference as in visibility dataset
|
|
568
|
+
"""
|
|
569
|
+
antenna_id: Coordof[AntennaArray]
|
|
570
|
+
"""
|
|
571
|
+
Antenna identifier, as specified by baseline_antenna1/2_id in visibility dataset
|
|
572
|
+
"""
|
|
573
|
+
sky_coord_label: Coord[SkyCoordLabel, str]
|
|
574
|
+
"""
|
|
575
|
+
Direction labels.
|
|
576
|
+
"""
|
|
577
|
+
|
|
578
|
+
BEAM_POINTING: Data[
|
|
579
|
+
Union[tuple[Time, AntennaId, TimePolynomial], tuple[Time, AntennaId]],
|
|
580
|
+
SkyCoordArray,
|
|
581
|
+
]
|
|
582
|
+
"""
|
|
583
|
+
Antenna pointing direction, optionally expressed as polynomial coefficients. DIRECTION in MSv3.
|
|
584
|
+
"""
|
|
585
|
+
DISH_MEASURED_POINTING: Optional[Data[tuple[Time, AntennaId], SkyCoordArray]]
|
|
586
|
+
"""
|
|
587
|
+
The current encoder values on the primary axes of the mount type for
|
|
588
|
+
the antenna. ENCODER in MSv3.
|
|
589
|
+
"""
|
|
590
|
+
OVER_THE_TOP: Optional[Data[tuple[Time, AntennaId], bool]]
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
@xarray_dataset_schema
|
|
594
|
+
class SpectralCoordXds:
|
|
595
|
+
# TODO
|
|
596
|
+
pass
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
@xarray_dataset_schema
|
|
600
|
+
class SourceXds:
|
|
601
|
+
# TODO
|
|
602
|
+
pass
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
@xarray_dataset_schema
|
|
606
|
+
class PhasedArrayXds:
|
|
607
|
+
# TODO
|
|
608
|
+
pass
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
@xarray_dataset_schema
|
|
612
|
+
class VisibilityXds:
|
|
613
|
+
"""TODO: documentation"""
|
|
614
|
+
|
|
615
|
+
# --- Required Coordinates ---
|
|
616
|
+
time: Coordof[TimeArray]
|
|
617
|
+
"""
|
|
618
|
+
The time coordinate is the mid-point of the nominal sampling interval, as
|
|
619
|
+
specified in the ``ms_v4.time.attrs['integration_time']`` (ms v2 interval).
|
|
620
|
+
"""
|
|
621
|
+
baseline_id: Coordof[BaselineArray]
|
|
622
|
+
frequency: Coordof[FrequencyArray]
|
|
623
|
+
"""Center frequencies for each channel."""
|
|
624
|
+
polarization: Coordof[PolarizationArray]
|
|
625
|
+
"""
|
|
626
|
+
Labels for polarization types, e.g. ``['XX','XY','YX','YY']``, ``['RR','RL','LR','LL']``.
|
|
627
|
+
"""
|
|
628
|
+
uvw_label: Optional[Coordof[UvwLabelArray]]
|
|
629
|
+
|
|
630
|
+
# --- Required data variables ---
|
|
631
|
+
VISIBILITY: Dataof[VisibilityArray]
|
|
632
|
+
|
|
633
|
+
# --- Required Attributes ---
|
|
634
|
+
antenna_xds: Attr[AntennaXds]
|
|
635
|
+
|
|
636
|
+
# --- Optional Coordinates ---
|
|
637
|
+
baseline_antenna1_id: Optional[Coordof[BaselineAntennaArray]] = None
|
|
638
|
+
"""Antenna id for 1st antenna in baseline. Maps to ``attrs['antenna_xds'].antenna_id``"""
|
|
639
|
+
baseline_antenna2_id: Optional[Coordof[BaselineAntennaArray]] = None
|
|
640
|
+
"""Antenna id for 2nd antenna in baseline. Maps to ``attrs['antenna_xds'].antenna_id``"""
|
|
641
|
+
scan_id: Optional[Coord[Time, int]] = None
|
|
642
|
+
"""Arbitary scan number to identify data taken in the same logical scan."""
|
|
643
|
+
|
|
644
|
+
# --- Optional data variables / arrays ---
|
|
645
|
+
"""Complex visibilities, either simulated or measured by interferometer."""
|
|
646
|
+
FLAG: Optional[Dataof[FlagArray]] = None
|
|
647
|
+
WEIGHT: Optional[Dataof[WeightArray]] = None
|
|
648
|
+
UVW: Optional[Dataof[UvwArray]] = None
|
|
649
|
+
EFFECTIVE_INTEGRATION_TIME: Optional[Dataof[TimeSamplingArray]] = None
|
|
650
|
+
"""
|
|
651
|
+
The integration time, including the effects of missing data, in contrast to
|
|
652
|
+
``integration_time`` attribute of the ``time`` coordinate,
|
|
653
|
+
see :py:class:`TimeArray`. (MS v2: ``exposure``).
|
|
654
|
+
"""
|
|
655
|
+
TIME_CENTROID: Optional[Dataof[TimeSamplingArray]] = None
|
|
656
|
+
"""
|
|
657
|
+
The time centroid of the visibility, includes the effects of missing data
|
|
658
|
+
unlike the ``time`` coordinate, see :py:class:`TimeArray`.
|
|
659
|
+
"""
|
|
660
|
+
TIME_CENTROID_EXTRA_PRECISION: Optional[Dataof[TimeSamplingArray]] = None
|
|
661
|
+
"""Additional precision for ``TIME_CENTROID``"""
|
|
662
|
+
EFFECTIVE_CHANNEL_WIDTH: Optional[Dataof[FreqSamplingArray]] = None
|
|
663
|
+
"""The channel bandwidth that includes the effects of missing data."""
|
|
664
|
+
FREQUENCY_CENTROID: Optional[Dataof[FreqSamplingArray]] = None
|
|
665
|
+
"""Includes the effects of missing data unlike ``frequency``."""
|
|
666
|
+
|
|
667
|
+
# --- Optional Attributes ---
|
|
668
|
+
pointing_xds: Optional[Attr[PointingXds]] = None
|
|
669
|
+
source_xds: Optional[Attr[SourceXds]] = None
|
|
670
|
+
pased_array_xds: Optional[Attr[PhasedArrayXds]] = None
|
|
671
|
+
observation_info: Optional[Attr[ObservationInfoDict]] = None
|
|
672
|
+
observation_info: Optional[Attr[ProcessorInfoDict]] = None
|
|
673
|
+
|
|
674
|
+
version: Optional[Attr[str]] = None # TODO:
|
|
675
|
+
"""Semantic version of xradio data format"""
|
|
676
|
+
creation_date: Optional[Attr[str]] = None
|
|
677
|
+
"""Date visibility dataset was created . Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
|
|
678
|
+
intent: Optional[Attr[str]] = None
|
|
679
|
+
"""Identifies the intention of the scan, such as to calibrate or observe a
|
|
680
|
+
target. See :ref:`scan intents` for possible values.
|
|
681
|
+
"""
|
|
682
|
+
data_description_id: Optional[Attr[str]] = None
|
|
683
|
+
"""
|
|
684
|
+
The id assigned to this combination of spectral window and polarization setup.
|
|
685
|
+
"""
|
|
686
|
+
|
|
687
|
+
type: Attr[str] = "visibility"
|