xradio 0.0.28__py3-none-any.whl → 0.0.29__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.
Files changed (48) hide show
  1. xradio/__init__.py +5 -4
  2. xradio/_utils/array.py +90 -0
  3. xradio/_utils/zarr/common.py +48 -3
  4. xradio/image/_util/zarr.py +4 -1
  5. xradio/schema/__init__.py +24 -6
  6. xradio/schema/bases.py +440 -2
  7. xradio/schema/check.py +96 -55
  8. xradio/schema/dataclass.py +123 -27
  9. xradio/schema/metamodel.py +21 -4
  10. xradio/schema/typing.py +33 -18
  11. xradio/vis/__init__.py +5 -2
  12. xradio/vis/_processing_set.py +28 -20
  13. xradio/vis/_vis_utils/_ms/_tables/create_field_and_source_xds.py +710 -0
  14. xradio/vis/_vis_utils/_ms/_tables/load.py +23 -10
  15. xradio/vis/_vis_utils/_ms/_tables/load_main_table.py +145 -64
  16. xradio/vis/_vis_utils/_ms/_tables/read.py +747 -172
  17. xradio/vis/_vis_utils/_ms/_tables/read_main_table.py +173 -44
  18. xradio/vis/_vis_utils/_ms/_tables/read_subtables.py +79 -28
  19. xradio/vis/_vis_utils/_ms/_tables/write.py +102 -45
  20. xradio/vis/_vis_utils/_ms/_tables/write_exp_api.py +127 -65
  21. xradio/vis/_vis_utils/_ms/chunks.py +58 -21
  22. xradio/vis/_vis_utils/_ms/conversion.py +536 -67
  23. xradio/vis/_vis_utils/_ms/descr.py +52 -20
  24. xradio/vis/_vis_utils/_ms/msv2_to_msv4_meta.py +70 -35
  25. xradio/vis/_vis_utils/_ms/msv4_infos.py +0 -59
  26. xradio/vis/_vis_utils/_ms/msv4_sub_xdss.py +76 -9
  27. xradio/vis/_vis_utils/_ms/optimised_functions.py +0 -46
  28. xradio/vis/_vis_utils/_ms/partition_queries.py +308 -119
  29. xradio/vis/_vis_utils/_ms/partitions.py +82 -25
  30. xradio/vis/_vis_utils/_ms/subtables.py +32 -14
  31. xradio/vis/_vis_utils/_utils/partition_attrs.py +30 -11
  32. xradio/vis/_vis_utils/_utils/xds_helper.py +136 -45
  33. xradio/vis/_vis_utils/_zarr/read.py +60 -22
  34. xradio/vis/_vis_utils/_zarr/write.py +83 -9
  35. xradio/vis/_vis_utils/ms.py +48 -29
  36. xradio/vis/_vis_utils/zarr.py +44 -20
  37. xradio/vis/convert_msv2_to_processing_set.py +106 -32
  38. xradio/vis/load_processing_set.py +38 -61
  39. xradio/vis/read_processing_set.py +62 -96
  40. xradio/vis/schema.py +687 -0
  41. xradio/vis/vis_io.py +75 -43
  42. {xradio-0.0.28.dist-info → xradio-0.0.29.dist-info}/LICENSE.txt +6 -1
  43. {xradio-0.0.28.dist-info → xradio-0.0.29.dist-info}/METADATA +10 -5
  44. xradio-0.0.29.dist-info/RECORD +73 -0
  45. {xradio-0.0.28.dist-info → xradio-0.0.29.dist-info}/WHEEL +1 -1
  46. xradio/vis/model.py +0 -497
  47. xradio-0.0.28.dist-info/RECORD +0 -71
  48. {xradio-0.0.28.dist-info → xradio-0.0.29.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"