xradio 0.0.41__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.
Files changed (62) hide show
  1. xradio/_utils/coord_math.py +100 -0
  2. xradio/_utils/list_and_array.py +49 -4
  3. xradio/_utils/schema.py +36 -16
  4. xradio/image/_util/_casacore/xds_from_casacore.py +5 -5
  5. xradio/image/_util/_casacore/xds_to_casacore.py +12 -11
  6. xradio/image/_util/_fits/xds_from_fits.py +18 -17
  7. xradio/image/_util/_zarr/zarr_low_level.py +29 -12
  8. xradio/image/_util/common.py +1 -1
  9. xradio/image/_util/image_factory.py +1 -1
  10. xradio/{correlated_data → measurement_set}/__init__.py +7 -4
  11. xradio/measurement_set/_utils/__init__.py +5 -0
  12. xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/load_main_table.py +1 -1
  13. xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/read.py +1 -1
  14. xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/conversion.py +78 -35
  15. xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/create_antenna_xds.py +62 -37
  16. xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/create_field_and_source_xds.py +109 -22
  17. xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/msv4_sub_xdss.py +47 -13
  18. xradio/{correlated_data → measurement_set}/_utils/_utils/xds_helper.py +1 -1
  19. xradio/{correlated_data/_utils/ms.py → measurement_set/_utils/msv2.py} +4 -4
  20. xradio/{correlated_data → measurement_set}/convert_msv2_to_processing_set.py +2 -2
  21. xradio/{correlated_data → measurement_set}/load_processing_set.py +5 -5
  22. xradio/measurement_set/measurement_set_xds.py +83 -0
  23. xradio/{correlated_data → measurement_set}/open_processing_set.py +9 -16
  24. xradio/measurement_set/processing_set.py +777 -0
  25. xradio/{correlated_data → measurement_set}/schema.py +1101 -610
  26. xradio/schema/check.py +42 -22
  27. xradio/schema/dataclass.py +56 -6
  28. xradio/sphinx/__init__.py +12 -0
  29. xradio/sphinx/schema_table.py +351 -0
  30. {xradio-0.0.41.dist-info → xradio-0.0.42.dist-info}/METADATA +9 -6
  31. xradio-0.0.42.dist-info/RECORD +76 -0
  32. {xradio-0.0.41.dist-info → xradio-0.0.42.dist-info}/WHEEL +1 -1
  33. xradio/_utils/common.py +0 -101
  34. xradio/correlated_data/_utils/__init__.py +0 -5
  35. xradio/correlated_data/correlated_xds.py +0 -13
  36. xradio/correlated_data/processing_set.py +0 -301
  37. xradio/correlated_data/test__processing_set.py +0 -74
  38. xradio-0.0.41.dist-info/RECORD +0 -75
  39. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/load.py +0 -0
  40. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/read_main_table.py +0 -0
  41. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/read_subtables.py +0 -0
  42. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/table_query.py +0 -0
  43. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/write.py +0 -0
  44. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/_tables/write_exp_api.py +0 -0
  45. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/chunks.py +0 -0
  46. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/descr.py +0 -0
  47. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/msv2_msv3.py +0 -0
  48. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/msv2_to_msv4_meta.py +0 -0
  49. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/msv4_info_dicts.py +0 -0
  50. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/optimised_functions.py +0 -0
  51. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/partition_queries.py +0 -0
  52. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/partitions.py +0 -0
  53. /xradio/{correlated_data/_utils/_ms → measurement_set/_utils/_msv2}/subtables.py +0 -0
  54. /xradio/{correlated_data → measurement_set}/_utils/_utils/cds.py +0 -0
  55. /xradio/{correlated_data → measurement_set}/_utils/_utils/partition_attrs.py +0 -0
  56. /xradio/{correlated_data → measurement_set}/_utils/_utils/stokes_types.py +0 -0
  57. /xradio/{correlated_data → measurement_set}/_utils/_zarr/encoding.py +0 -0
  58. /xradio/{correlated_data → measurement_set}/_utils/_zarr/read.py +0 -0
  59. /xradio/{correlated_data → measurement_set}/_utils/_zarr/write.py +0 -0
  60. /xradio/{correlated_data → measurement_set}/_utils/zarr.py +0 -0
  61. {xradio-0.0.41.dist-info → xradio-0.0.42.dist-info}/LICENSE.txt +0 -0
  62. {xradio-0.0.41.dist-info → xradio-0.0.42.dist-info}/top_level.txt +0 -0
@@ -12,12 +12,16 @@ import numpy
12
12
  # Dimensions
13
13
  Time = Literal["time"]
14
14
  """ Observation time dimension """
15
- TimePointing = Literal["time_pointing"]
16
- """ time dimension of pointing dataset (when not interpolated to main time) """
15
+ TimeCal = Literal["time_cal"]
16
+ """ time dimension of system calibration (when not interpolated to main time)"""
17
17
  TimeEphemeris = Literal["time_ephemeris"]
18
18
  """ time dimension of ephemeris data (when not interpolated to main time) """
19
- TimeCal = Literal["time_cal"]
20
- """ time dimension of system calibration (when not interpolated to main time) """
19
+ TimePhaseCal = Literal["time_phase_cal"]
20
+ """ Coordinate label for VLBI-specific phase cal time axis """
21
+ TimePointing = Literal["time_pointing"]
22
+ """ time dimension of pointing dataset (when not interpolated to main time) """
23
+ TimeWeather = Literal["time_weather"]
24
+ """ time dimension of weather dataset (when not interpolated to main time) """
21
25
  AntennaName = Literal["antenna_name"]
22
26
  """ Antenna name dimension """
23
27
  StationName = Literal["station_name"]
@@ -50,8 +54,6 @@ EllipsoidPosLabel = Literal["ellipsoid_pos_label"]
50
54
  """ Coordinate labels of geodetic earth location data (typically shape 3 and 'lon', 'lat', 'height')"""
51
55
  CartesianPosLabel = Literal["cartesian_pos_label"]
52
56
  """ Coordinate labels of geocentric earth location data (typically shape 3 and 'x', 'y', 'z')"""
53
- TimePhaseCal = Literal["time_phase_cal"]
54
- """ Coordinate label for VLBI-specific phase cal time axis """
55
57
  nPolynomial = Literal["n_polynomial"]
56
58
  """ For data that is represented as variable in time using Taylor expansion """
57
59
  PolyTerm = Literal["poly_term"]
@@ -63,13 +65,157 @@ LineLabel = Literal["line_label"]
63
65
  # zero dimensions.
64
66
  ZD = tuple[()]
65
67
 
68
+
69
+ # Types of quantity and measures
70
+ Quantity = Literal["quantity"]
71
+ SkyCoord = Literal["sky_coord"]
72
+ SpectralCoord = Literal["spectral_coord"]
73
+ Location = Literal["location"]
74
+ Doppler = Literal["doppler"]
75
+
76
+
77
+ # Units of quantities and measures
78
+ UnitsSeconds = list[Literal["s"]]
79
+ UnitsHertz = list[Literal["Hz"]]
80
+ UnitsMeters = list[Literal["m"]]
81
+
82
+ UnitsOfSkyCoordInRadians = list[Literal["rad"], Literal["rad"]]
83
+ UnitsOfLocationInMetersOrRadians = Union[
84
+ list[Literal["m"], Literal["m"], Literal["m"]],
85
+ list[Literal["rad"], Literal["rad"], Literal["m"]],
86
+ ]
87
+ UnitsOfPositionInRadians = list[Literal["rad"], Literal["rad"], Literal["m"]]
88
+ UnitsOfDopplerShift = Union[list[Literal["ratio"]], list[Literal["m/s"]]]
89
+
90
+ UnitsRadians = list[Literal["rad"]]
91
+ UnitsKelvin = list[Literal["K"]]
92
+ UnitsKelvinPerJansky = list[Literal["K/Jy"]]
93
+ UnitsMetersPerSecond = list[Literal["m/s"]]
94
+ UnitsPascal = list[Literal["Pa"]] # hPa? (in MSv2)
95
+ UnitsPerSquareMeters = list[Literal["/m^2"]]
96
+
97
+
66
98
  # Quantities
67
99
 
68
100
 
101
+ @xarray_dataarray_schema
102
+ class QuantityInSecondsArray:
103
+ """
104
+ Quantity with units of seconds
105
+ """
106
+
107
+ data: Data[ZD, float]
108
+
109
+ units: Attr[UnitsSeconds]
110
+ type: Attr[Quantity] = "quantity"
111
+
112
+
113
+ @xarray_dataarray_schema
114
+ class QuantityInHertzArray:
115
+ """
116
+ Quantity with units of Hertz
117
+ """
118
+
119
+ data: Data[ZD, float]
120
+
121
+ units: Attr[UnitsHertz]
122
+ type: Attr[Quantity] = "quantity"
123
+
124
+
125
+ @xarray_dataarray_schema
126
+ class QuantityInMetersArray:
127
+ """
128
+ Quantity with units of Hertz
129
+ """
130
+
131
+ data: Data[ZD, float]
132
+
133
+ units: Attr[UnitsMeters]
134
+ type: Attr[Quantity] = "quantity"
135
+
136
+
137
+ @xarray_dataarray_schema
138
+ class QuantityInMetersPerSecondArray:
139
+ """
140
+ Quantity with units of Hertz
141
+ """
142
+
143
+ data: Data[ZD, float]
144
+
145
+ units: Attr[UnitsMetersPerSecond]
146
+ type: Attr[Quantity] = "quantity"
147
+
148
+
149
+ @xarray_dataarray_schema
150
+ class QuantityInRadiansArray:
151
+ """
152
+ Quantity with units of Hertz
153
+ """
154
+
155
+ data: Data[ZD, float]
156
+
157
+ units: Attr[UnitsRadians]
158
+ type: Attr[Quantity] = "quantity"
159
+
160
+
161
+ @xarray_dataarray_schema
162
+ class QuantityInKelvinArray:
163
+ """
164
+ Quantity with units of Kelvins
165
+ """
166
+
167
+ data: Data[ZD, float]
168
+
169
+ units: Attr[UnitsKelvin]
170
+ type: Attr[Quantity] = "quantity"
171
+
172
+
173
+ @xarray_dataarray_schema
174
+ class QuantityInKelvinPerJanskyArray:
175
+ """
176
+ Quantity with units of K/Jy (sensitivity in gain curve)
177
+ """
178
+
179
+ data: Data[ZD, numpy.float64]
180
+
181
+ units: Attr[UnitsKelvinPerJansky]
182
+ type: Attr[Quantity] = "quantity"
183
+
184
+
185
+ @xarray_dataarray_schema
186
+ class QuantityInPascalArray:
187
+ """
188
+ Quantity with units of Pa
189
+ """
190
+
191
+ data: Data[ZD, numpy.float64]
192
+
193
+ units: Attr[UnitsPascal]
194
+ type: Attr[Quantity] = "quantity"
195
+
196
+
197
+ @xarray_dataarray_schema
198
+ class QuantityInPerSquareMetersArray:
199
+ """
200
+ Quantity with units of /m^2
201
+ """
202
+
203
+ data: Data[ZD, numpy.float64]
204
+
205
+ units: Attr[UnitsPerSquareMeters]
206
+ type: Attr[Quantity] = "quantity"
207
+
208
+
209
+ AllowedTimeScales = Literal["tai", "tcb", "tcg", "tdb", "tt", "ut1", "utc"]
210
+
211
+
212
+ AllowedTimeFormats = Literal["unix", "mjd", "cxcsec", "gps"]
213
+
214
+
69
215
  @xarray_dataarray_schema
70
216
  class TimeArray:
71
217
  """
72
- Representation of a time quantity.
218
+ Representation of a time measure.
73
219
 
74
220
  :py:class:`astropy.time.Time` serves as the reference implementation.
75
221
  Data can be converted as follows::
@@ -91,26 +237,64 @@ class TimeArray:
91
237
  data: Data[ZD, float]
92
238
  """Time since epoch, typically in seconds (see ``units``)."""
93
239
 
94
- scale: Attr[str] = "tai"
240
+ type: Attr[Time] = "time"
241
+ """ Array type. Should be ``"time"``. """
242
+ units: Attr[UnitsSeconds] = ("s",)
243
+ """ Units to associate with axis"""
244
+ scale: Attr[AllowedTimeScales] = "utc"
95
245
  """
96
246
  Time scale of data. Must be one of ``(‘tai’, ‘tcb’, ‘tcg’, ‘tdb’, ‘tt’, ‘ut1’, ‘utc’)``,
97
247
  see :py:class:`astropy.time.Time`
98
248
  """
99
- format: Attr[str] = "unix_tai"
249
+ format: Attr[AllowedTimeFormats] = "unix"
100
250
  """Time representation and epoch, see :py:class:`TimeArray`."""
101
251
 
102
- type: Attr[str] = "time"
103
- units: Attr[list[str]] = ("s",)
252
+
253
+ # Taken from the list of astropy built-in frame classes: https://docs.astropy.org/en/stable/coordinates/index.html
254
+ AllowedSkyCoordFrames = Literal[
255
+ "icrs",
256
+ "fk5",
257
+ "fk4",
258
+ "fk4noterms",
259
+ "galactic",
260
+ "galactocentric",
261
+ "supergalactic",
262
+ "altaz",
263
+ "hadec",
264
+ "gcrs",
265
+ "cirs",
266
+ "itrs",
267
+ "hcrs",
268
+ "teme",
269
+ "tete",
270
+ "precessedgeocentric",
271
+ "geocentricmeanecliptic",
272
+ "barycentricmeanecliptic",
273
+ "heliocentricmeanecliptic",
274
+ "geocentrictrueecliptic",
275
+ "barycentrictrueecliptic",
276
+ "heliocentrictrueecliptic",
277
+ "heliocentriceclipticiau76",
278
+ "custombarycentricecliptic",
279
+ "lsr",
280
+ "lsrk",
281
+ "lsrd",
282
+ "galacticlsr",
283
+ ]
104
284
 
105
285
 
106
286
  @xarray_dataarray_schema
107
287
  class SkyCoordArray:
288
+ """Measures array for data variables that are sky coordinates, used in :py:class:`FieldSourceXds`"""
289
+
108
290
  data: Data[Union[SkyDirLabel, SkyPosLabel], float]
109
291
 
110
- type: Attr[str] = "sky_coord"
111
- units: Attr[list[str]] = ("rad", "rad")
112
- frame: Attr[str] = ""
292
+ type: Attr[SkyCoord] = "sky_coord"
293
+ units: Attr[UnitsOfSkyCoordInRadians] = ("rad", "rad")
294
+ frame: Attr[AllowedSkyCoordFrames] = ""
113
295
  """
296
+ Possible values are astropy SkyCoord frames.
297
+ Several casacore frames found in MSv2 are translated to astropy frames as follows: AZELGEO=>altaz, J2000=>fk5, ICRS=>icrs.
114
298
  From fixvis docs: clean and the im tool ignore the reference frame
115
299
  claimed by the UVW column (it is often mislabelled as ITRF when it is
116
300
  really FK5 (J2000)) and instead assume the (u, v, w)s are in the same frame
@@ -122,65 +306,61 @@ class SkyCoordArray:
122
306
 
123
307
  @xarray_dataarray_schema
124
308
  class LocalSkyCoordArray:
125
- """Coordinate array for the arrays that have coordinate local_sky_dir_label
126
- in pointing_xds"""
309
+ """Measures array for the arrays that have coordinate local_sky_dir_label in :py:class:`PointingXds`"""
127
310
 
128
311
  data: Data[LocalSkyDirLabel, float]
129
312
 
130
- type: Attr[str] = "sky_coord"
131
- units: Attr[list[str]] = ("rad", "rad")
132
- frame: Attr[str] = ""
313
+ type: Attr[SkyCoord] = "sky_coord"
314
+ units: Attr[UnitsOfSkyCoordInRadians] = ("rad", "rad")
315
+ frame: Attr[AllowedSkyCoordFrames] = "fk5"
133
316
  """
317
+ From fixvis docs: clean and the im tool ignore the reference frame claimed by the UVW column (it is often mislabelled
318
+ as ITRF when it is really FK5 (J2000)) and instead assume the (u, v, w)s are in the same frame as the phase tracking
319
+ center. calcuvw does not yet force the UVW column and field centers to use the same reference frame! Blank = use the
320
+ phase tracking frame of vis.
134
321
  """
135
322
 
136
323
 
324
+ # Coordinates / Axes
137
325
  @xarray_dataarray_schema
138
- class SkyCoordOffsetArray:
139
- data: Data[Union[SkyDirLabel, SkyPosLabel], float]
140
-
141
- type: Attr[str] = "sky_coord"
142
- units: Attr[list[str]] = ("rad", "rad")
326
+ class TimeCoordArray:
327
+ """Data model of the main dataset time axis. See also :py:class:`TimeArray`."""
143
328
 
144
-
145
- @xarray_dataarray_schema
146
- class QuantityArray:
329
+ data: Data[Time, float]
147
330
  """
148
- Anonymous quantity, possibly with associated units
149
-
150
- Often used for distances / differences (integration time, channel width etcetera).
331
+ Time, expressed in seconds since the epoch (see ``scale`` &
332
+ ``format``), see also see :py:class:`TimeArray`.
151
333
  """
152
334
 
153
- data: Data[ZD, float]
335
+ type: Attr[Time] = "time"
336
+ """ Coordinate type. Should be ``"time"``. """
154
337
 
155
- units: Attr[list[str]]
156
- type: Attr[str] = "quantity"
338
+ units: Attr[UnitsSeconds] = ("s",)
339
+ """ Units to associate with axis"""
157
340
 
341
+ scale: Attr[AllowedTimeScales] = "utc"
342
+ """ Astropy time scales, see :py:class:`TimeArray` """
158
343
 
159
- # Coordinates / Axes
160
- class TimeCoordArrayBase:
161
- """Base class with the metadata found in time array coords."""
344
+ format: Attr[AllowedTimeFormats] = "unix"
345
+ """ Astropy format, see :py:class:`TimeArray`"""
162
346
 
163
- integration_time: Optional[Attr[QuantityArray]] = None
347
+ integration_time: Attr[QuantityInSecondsArray] = None
164
348
  """ The nominal sampling interval (ms v2). Units of seconds. """
165
- effective_integration_time: Optional[Attr[str]] = None
166
- """
167
- Name of data array that contains the integration time that includes
168
- the effects of missing data.
169
- """
170
-
171
- units: Attr[list[str]] = ("s",)
172
- """ Units to associate with axis"""
173
- scale: Attr[str] = "tai"
174
- """ Astropy time scales, see :py:class:`TimeArray` """
175
- format: Attr[str] = "unix"
176
- """ Astropy format, see :py:class:`TimeArray`"""
177
- long_name: Optional[Attr[str]] = "Observation Time"
178
- """ Long-form name to use for axis"""
179
349
 
180
350
 
181
351
  @xarray_dataarray_schema
182
- class TimeCoordArray(TimeCoordArrayBase):
183
- """Data model of visibility time axis. See also :py:class:`TimeArray`."""
352
+ class TimeInterpolatedCoordArray:
353
+ """
354
+ Data model of a time axis when it is interpolated to match the time
355
+ axis of the main dataset. This can be used in the system_calibration_xds,
356
+ pointing_xds, weather_xds, field_and_source_info_xds, and phase_cal_xds
357
+ when their respective time_cal, time_pointing, time_weather,
358
+ time_ephemeris or time_phase_cal are interpolated to the main dataset
359
+ time. See also :py:class:`TimeArray`.
360
+
361
+ The only difference with respect to the main TimeCoordArray is the
362
+ absence of the attribute integration_time
363
+ """
184
364
 
185
365
  data: Data[Time, float]
186
366
  """
@@ -188,14 +368,23 @@ class TimeCoordArray(TimeCoordArrayBase):
188
368
  ``format``), see also see :py:class:`TimeArray`.
189
369
  """
190
370
 
191
- type: Attr[str] = "time"
371
+ type: Attr[Time] = "time"
192
372
  """ Coordinate type. Should be ``"time"``. """
193
373
 
374
+ units: Attr[UnitsSeconds] = ("s",)
375
+ """ Units to associate with axis"""
376
+
377
+ scale: Attr[AllowedTimeScales] = "utc"
378
+ """ Astropy time scales, see :py:class:`TimeArray` """
379
+
380
+ format: Attr[AllowedTimeFormats] = "unix"
381
+ """ Astropy format, see :py:class:`TimeArray`"""
382
+
194
383
 
195
384
  @xarray_dataarray_schema
196
- class TimeCalCoordArray(TimeCoordArrayBase):
385
+ class TimeCalCoordArray:
197
386
  """Data model of 'time_cal' axis (time axis in system_calibration_xds
198
- when not interpolated to the main time axis. See also
387
+ subdataset when not interpolated to the main time axis. See also
199
388
  :py:class:`TimeCoordArray`."""
200
389
 
201
390
  data: Data[TimeCal, float]
@@ -204,14 +393,23 @@ class TimeCalCoordArray(TimeCoordArrayBase):
204
393
  ``format``).
205
394
  """
206
395
 
207
- type: Attr[str] = "time_cal"
396
+ type: Attr[Time] = "time_cal"
208
397
  """ Coordinate type. Should be ``"time_cal"``. """
209
398
 
399
+ units: Attr[UnitsSeconds] = ("s",)
400
+ """ Units to associate with axis"""
401
+
402
+ scale: Attr[AllowedTimeScales] = "utc"
403
+ """ Astropy time scales, see :py:class:`TimeArray` """
404
+
405
+ format: Attr[AllowedTimeFormats] = "unix"
406
+ """ Astropy format, see :py:class:`TimeArray`"""
407
+
210
408
 
211
409
  @xarray_dataarray_schema
212
- class TimePointingCoordArray(TimeCoordArrayBase):
213
- """Data model of 'time_pointing' axis (time axis in pointing_xds
214
- when not interpolated to the main time axis. See also
410
+ class TimePointingCoordArray:
411
+ """Data model of the 'time_pointing' axis (time axis in pointing_xds
412
+ subdataset when not interpolated to the main time axis. See also
215
413
  :py:class:`TimeCoordArray`."""
216
414
 
217
415
  data: Data[TimePointing, float]
@@ -220,15 +418,24 @@ class TimePointingCoordArray(TimeCoordArrayBase):
220
418
  ``format``).
221
419
  """
222
420
 
223
- type: Attr[str] = "time_pointing"
421
+ type: Attr[TimePointing] = "time_pointing"
224
422
  """ Coordinate type. Should be ``"time_pointing"``. """
225
423
 
424
+ units: Attr[UnitsSeconds] = ("s",)
425
+ """ Units to associate with axis"""
426
+
427
+ scale: Attr[AllowedTimeScales] = "utc"
428
+ """ Astropy time scales, see :py:class:`TimeArray` """
429
+
430
+ format: Attr[AllowedTimeFormats] = "unix"
431
+ """ Astropy format, see :py:class:`TimeArray`"""
432
+
226
433
 
227
434
  @xarray_dataarray_schema
228
- class TimeEphemerisCoordArray(TimeCoordArrayBase):
229
- """Data model of 'time_ephemeris' axis (time axis in field_and_source_info_xds
230
- when not interpolated to the main time axis. See also
231
- :py:class:`TimeCoordArray`."""
435
+ class TimeEphemerisCoordArray:
436
+ """Data model of the 'time_ephemeris' axis (time axis in the
437
+ field_and_source_info_xds subdataset when not interpolated to the main
438
+ time axis. See also :py:class:`TimeCoordArray`."""
232
439
 
233
440
  data: Data[TimeEphemeris, float]
234
441
  """
@@ -236,71 +443,129 @@ class TimeEphemerisCoordArray(TimeCoordArrayBase):
236
443
  ``format``).
237
444
  """
238
445
 
239
- type: Attr[str] = "time_ephemeris"
446
+ type: Attr[TimeEphemeris] = "time_ephemeris"
240
447
  """ Coordinate type. Should be ``"time_ephemeris"``. """
241
448
 
449
+ units: Attr[UnitsSeconds] = ("s",)
450
+ """ Units to associate with axis"""
451
+
452
+ scale: Attr[AllowedTimeScales] = "utc"
453
+ """ Astropy time scales, see :py:class:`TimeArray` """
454
+
455
+ format: Attr[AllowedTimeFormats] = "unix"
456
+ """ Astropy format, see :py:class:`TimeArray`"""
457
+
242
458
 
243
459
  @xarray_dataarray_schema
244
- class SpectralCoordArray:
245
- data: Data[ZD, float]
460
+ class TimeWeatherCoordArray:
461
+ """Data model of the 'time_weather' axis (time axis in the weather_xds
462
+ subdataset when not interpolated to the main time axis. See also
463
+ :py:class:`TimeCoordArray`."""
246
464
 
247
- frame: Attr[str] = "gcrs"
248
- """Astropy time scales."""
465
+ data: Data[TimeWeather, float]
466
+ """
467
+ Time, expressed in seconds since the epoch (see ``scale`` &
468
+ ``format``).
469
+ """
249
470
 
250
- type: Attr[str] = "frequency"
251
- units: Attr[list[str]] = ("Hz",)
471
+ type: Attr[Time] = "time_weather"
472
+ """ Coordinate type. Should be ``"time_weather"``. """
252
473
 
474
+ units: Attr[UnitsSeconds] = ("s",)
475
+ """ Units to associate with axis"""
476
+
477
+ scale: Attr[AllowedTimeScales] = "utc"
478
+ """ Astropy time scales, see :py:class:`TimeArray` """
479
+
480
+ format: Attr[AllowedTimeFormats] = "unix"
481
+ """ Astropy format, see :py:class:`TimeArray`"""
253
482
 
254
- @xarray_dataarray_schema
255
- class EarthLocationArray:
256
- data: Data[CartesianPosLabel, float]
257
483
 
258
- ellipsoid: Attr[str]
484
+ # For now allowing both some of the casacore frames (from "REST" to "TOPO" - all in uppercase) as well as
485
+ # the astropy frames (all in lowercase, taken from the list of SpectralCoord:
486
+ # https://docs.astropy.org/en/stable/coordinates/spectralcoord.html)
487
+ AllowedSpectralCoordFrames = Literal[
488
+ "REST",
489
+ # "LSRK" -> "lsrk",
490
+ # "LSRD" -> "lsrd",
491
+ "BARY",
492
+ "GEO",
493
+ "TOPO",
494
+ # astropy frames
495
+ "gcrs",
496
+ "icrs",
497
+ "hcrs",
498
+ "lsrk",
499
+ "lsrd",
500
+ "lsr",
501
+ ]
502
+
503
+
504
+ @xarray_dataarray_schema
505
+ class SpectralCoordArray:
259
506
  """
260
- ITRF makes use of GRS80 ellipsoid and WGS84 makes use of WGS84 ellipsoid
507
+ Measures array for data variables and attributes that are spectral coordinates.
261
508
  """
262
- units: Attr[list[str]] = ("m", "m", "m")
509
+
510
+ data: Data[ZD, float]
511
+
512
+ units: Attr[UnitsHertz] = ("Hz",)
513
+
514
+ observer: Attr[AllowedSpectralCoordFrames] = "gcrs"
263
515
  """
264
- If the units are a list of strings then it must be the same length as
265
- the last dimension of the data array. This allows for having different
266
- units in the same data array,for example geodetic coordinates could use
267
- ``['rad','rad','m']``.
516
+ Capitalized reference observers are from casacore. TOPO implies creating astropy earth_location.
517
+ Astropy velocity reference frames are lowercase. Note that Astropy does not use the name 'TOPO' (telescope centric)
518
+ rather it assumes if no velocity frame is given that this is the default.
268
519
  """
269
520
 
521
+ type: Attr[SpectralCoord] = "spectral_coord"
522
+
523
+
524
+ AllowedLocationFrames = Literal["ITRF", "GRS80", "WGS84", "WGS72", "Undefined"]
525
+
526
+
527
+ AllowedLocationCoordinateSystems = Literal[
528
+ "geocentric",
529
+ "planetcentric",
530
+ "geodetic",
531
+ "planetodetic",
532
+ "orbital",
533
+ ]
534
+
270
535
 
271
536
  @xarray_dataarray_schema
272
537
  class LocationArray:
273
538
  """
274
- Measure type used for example in field_and_source_xds/OBSERVER_POSITION
539
+ Measure type used for example in antenna_xds/ANTENNA_POSITION, field_and_source_xds/OBSERVER_POSITION
275
540
  Data dimensions can be EllipsoidPosLabel or CartesianPosLabel
276
541
  """
277
542
 
278
543
  data: Data[Union[EllipsoidPosLabel, CartesianPosLabel], float]
279
544
 
280
- ellipsoid: Attr[str]
545
+ units: Attr[UnitsOfLocationInMetersOrRadians]
546
+ """
547
+ If the units are a list of strings then it must be the same length as
548
+ the last dimension of the data array. This allows for having different
549
+ units in the same data array,for example geodetic coordinates could use
550
+ ``['rad','rad','m']``.
551
+ """
552
+
553
+ frame: Attr[AllowedLocationFrames]
281
554
  """
282
- ITRF makes use of GRS80 ellipsoid and WGS84 makes use of WGS84 ellipsoid
555
+ Can be ITRF, GRS80, WGS84, WGS72, Undefined
283
556
  """
284
557
 
558
+ coordinate_system: Attr[AllowedLocationCoordinateSystems]
559
+ """ Can be ``geocentric/planetcentric, geodetic/planetodetic, orbital`` """
560
+
285
561
  origin_object_name: Attr[str]
286
562
  """
287
563
  earth/sun/moon/etc
288
564
  """
289
565
 
290
- coordinate_system: Attr[str]
291
- """ geocentric/planetcentric, geodetic/planetodetic, orbital """
292
-
293
- type: Attr[str] = "location"
566
+ type: Attr[Location] = "location"
294
567
  """ """
295
568
 
296
- units: Attr[list[str]] = ("deg", "deg", "m")
297
- """
298
- If the units are a list of strings then it must be the same length as
299
- the last dimension of the data array. This allows for having different
300
- units in the same data array,for example geodetic coordinates could use
301
- ``['rad','rad','m']``.
302
- """
303
-
304
569
 
305
570
  @xarray_dataarray_schema
306
571
  class EllipsoidPosLocationArray:
@@ -310,23 +575,23 @@ class EllipsoidPosLocationArray:
310
575
 
311
576
  data: Data[EllipsoidPosLabel, float]
312
577
 
313
- ellipsoid: Attr[str]
578
+ frame: Attr[AllowedLocationFrames]
314
579
  """
315
- ITRF makes use of GRS80 ellipsoid and WGS84 makes use of WGS84 ellipsoid
580
+ Can be ITRF, GRS80, WGS84, WGS72
316
581
  """
317
582
 
583
+ coordinate_system: Attr[AllowedLocationCoordinateSystems]
584
+ """ Can be ``geocentric/planetcentric, geodetic/planetodetic, orbital`` """
585
+
318
586
  origin_object_name: Attr[str]
319
587
  """
320
588
  earth/sun/moon/etc
321
589
  """
322
590
 
323
- coordinate_system: Attr[str]
324
- """ geocentric/planetcentric, geodetic/planetodetic, orbital """
325
-
326
- type: Attr[str] = "location"
591
+ type: Attr[Location] = "location"
327
592
  """ """
328
593
 
329
- units: Attr[list[str]] = ("deg", "deg", "m")
594
+ units: Attr[UnitsOfPositionInRadians] = ("rad", "rad", "m")
330
595
  """
331
596
  If the units are a list of strings then it must be the same length as
332
597
  the last dimension of the data array. This allows for having different
@@ -335,280 +600,64 @@ class EllipsoidPosLocationArray:
335
600
  """
336
601
 
337
602
 
338
- @xarray_dataset_schema
339
- class FieldSourceXds:
340
- """
341
- Field positions for each source.
603
+ @xarray_dataarray_schema
604
+ class BaselineArray:
605
+ """Model of the baseline_id coordinate in the main dataset (interferometric data, :py:class:`VisibiiltyXds`)"""
342
606
 
343
- Defines a field position on the sky. For interferometers, this is the correlated field position.
344
- For single dishes, this is the nominal pointing direction.
607
+ data: Data[BaselineId, Union[numpy.int64, numpy.int32]]
608
+ """Unique id for each baseline."""
609
+ long_name: Optional[Attr[str]] = "Baseline ID"
610
+
611
+
612
+ @xarray_dataarray_schema
613
+ class BaselineAntennaNameArray:
614
+ """Array of antenna_name by baseline_id, as used in main_xds and main_sd_xds
615
+ (antenna_name by baseline_id dim"""
616
+
617
+ data: Data[BaselineId, str]
618
+ """Unique id for each baseline."""
619
+ long_name: Optional[Attr[str]] = "Antenna name by baseline_id"
620
+
621
+
622
+ @xarray_dataarray_schema
623
+ class AntennaNameArray:
624
+ """
625
+ Model of the antenna_name coordinate, used in the main dataset (single dish data, :py:class:`VisibiiltyXds`)
626
+ and several sub-datasets such as antenna_xds, pointing_xds, weather_xds, system_calibration_xds, gain_curve_xds, etc.
345
627
  """
346
628
 
347
- source_name: Optional[Coord[Union[ZD, Time], str]]
348
- """ Source name. """
349
- field_name: Optional[Coord[Union[ZD, Time], str]]
350
- """Field name."""
629
+ data: Data[AntennaName, str]
630
+ """Unique name for each antenna(_station)."""
631
+ long_name: Optional[Attr[str]] = "Antenna name"
351
632
 
352
- time: Optional[Coordof[TimeCoordArray]]
353
- """Midpoint of time for which this set of parameters is accurate. Labeled 'time' when interpolated to main time """
354
- time_ephemeris: Optional[Coordof[TimeEphemerisCoordArray]]
355
- """Midpoint of time for which this set of parameters is accurate. Labeled 'time_ephemeris' when not interpolating to main time """
356
633
 
357
- line_label: Optional[Coord[LineLabel, str]]
358
- """ Line labels (for line names and variables). """
634
+ AllowedDopplerTypes = Literal[
635
+ "radio", "optical", "z", "ratio", "true", "relativistic", "beta", "gamma"
636
+ ]
359
637
 
360
- line_names: Optional[
361
- Coord[
362
- Union[
363
- tuple[LineLabel],
364
- tuple[Time, LineLabel],
365
- tuple[TimeEphemeris, LineLabel],
366
- ],
367
- str,
368
- ]
369
- ]
370
- """ Line names (e.g. v=1, J=1-0, SiO). """
371
638
 
372
- FIELD_PHASE_CENTER: Optional[
373
- Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], SkyCoordOffsetArray]
374
- ]
639
+ @xarray_dataarray_schema
640
+ class DopplerArray:
641
+ """Doppler measure information for the frequency coordinate"""
642
+
643
+ data: Data[ZD, numpy.float64]
644
+
645
+ type: Attr[Doppler] = "doppler"
646
+ """ Coordinate type. Should be ``"spectral_coord"``. """
647
+
648
+ units: Attr[UnitsOfDopplerShift] = ("m/s",)
649
+ """ Units to associate with axis, [ratio]/[m/s]"""
650
+
651
+ doppler_type: Attr[AllowedDopplerTypes] = "radio"
375
652
  """
376
- Offset from the SOURCE_DIRECTION that gives the direction of phase
377
- center for which the fringes have been stopped-that is a point source in
378
- this direction will produce a constant measured phase (page 2 of
379
- https://articles.adsabs.harvard.edu/pdf/1999ASPC..180...79F). For
380
- conversion from MSv2, frame refers column keywords by default. If frame
381
- varies with field, it refers DelayDir_Ref column instead.
653
+ Allowable values: radio, optical, z, ratio, true, relativistic, beta, gamma.
654
+ Astropy only has radio and optical. Using casacore types: https://casadocs.readthedocs.io/en/stable/notebooks/memo-series.html?highlight=Spectral%20Frames#Spectral-Frames
382
655
  """
383
656
 
384
- SOURCE_LOCATION: Optional[
385
- Data[
386
- Union[
387
- ZD,
388
- tuple[Time],
389
- tuple[TimeEphemeris],
390
- ],
391
- SkyCoordArray,
392
- ]
393
- ]
394
- """
395
- CASA Table Cols: RA,DEC,Rho."Astrometric RA and Dec and Geocentric
396
- distance with respect to the observer’s location (Geocentric). "Adjusted
397
- for light-time aberration only. With respect to the reference plane and
398
- equinox of the chosen system (ICRF or FK4/B1950). If the FK4/B1950 frame
399
- output is selected, elliptic aberration terms are added. Astrometric RA/DEC
400
- is generally used when comparing or reducing data against a star catalog."
401
- https://ssd.jpl.nasa.gov/horizons/manual.html : 1. Astrometric RA & DEC
402
- """
403
-
404
- LINE_REST_FREQUENCY: Optional[
405
- Data[
406
- Union[
407
- tuple[LineLabel],
408
- tuple[Time, LineLabel],
409
- tuple[TimeEphemeris, LineLabel],
410
- ],
411
- SpectralCoordArray,
412
- ]
413
- ]
414
- """ Rest frequencies for the transitions. """
415
-
416
- LINE_SYSTEMIC_VELOCITY: Optional[
417
- Data[
418
- Union[
419
- tuple[LineLabel],
420
- tuple[Time, LineLabel],
421
- tuple[TimeEphemeris, LineLabel],
422
- ],
423
- QuantityArray,
424
- ]
425
- ]
426
- """ Systemic velocity at reference """
427
-
428
- SOURCE_RADIAL_VELOCITY: Optional[
429
- Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityArray]
430
- ]
431
- """ CASA Table Cols: RadVel. Geocentric distance rate """
432
-
433
- NORTH_POLE_POSITION_ANGLE: Optional[
434
- Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityArray]
435
- ]
436
- """ CASA Table cols: NP_ang, "Targets' apparent north-pole position angle (counter-clockwise with respect to direction of true-of-date reference-frame north pole) and angular distance from the sub-observer point (center of disc) at print time. A negative distance indicates the north-pole is on the hidden hemisphere." https://ssd.jpl.nasa.gov/horizons/manual.html : 17. North pole position angle & distance from disc center. """
437
-
438
- NORTH_POLE_ANGULAR_DISTANCE: Optional[
439
- Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityArray]
440
- ]
441
- """ CASA Table cols: NP_dist, "Targets' apparent north-pole position angle (counter-clockwise with respect to direction of true-of date reference-frame north pole) and angular distance from the sub-observer point (center of disc) at print time. A negative distance indicates the north-pole is on the hidden hemisphere."https://ssd.jpl.nasa.gov/horizons/manual.html : 17. North pole position angle & distance from disc center. """
442
-
443
- SUB_OBSERVER_DIRECTION: Optional[
444
- Data[
445
- Union[
446
- ZD,
447
- tuple[Time],
448
- tuple[TimeEphemeris],
449
- ],
450
- EllipsoidPosLocationArray,
451
- ]
452
- ]
453
- """ CASA Table cols: DiskLong, DiskLat. "Apparent planetodetic longitude and latitude of the center of the target disc seen by the OBSERVER at print-time. This is not exactly the same as the "nearest point" for a non-spherical target shape (since the center of the disc might not be the point closest to the observer), but is generally very close if not a very irregular body shape. The IAU2009 rotation models are used except for Earth and MOON, which use higher-precision models. For the gas giants Jupiter, Saturn, Uranus and Neptune, IAU2009 longitude is based on the "System III" prime meridian rotation angle of the magnetic field. By contrast, pole direction (thus latitude) is relative to the body dynamical equator. There can be an offset between the magnetic pole and the dynamical pole of rotation. Down-leg light travel-time from target to observer is taken into account. Latitude is the angle between the equatorial plane and perpendicular to the reference ellipsoid of the body and body oblateness thereby included. The reference ellipsoid is an oblate spheroid with a single flatness coefficient in which the y-axis body radius is taken to be the same value as the x-axis radius. Whether longitude is positive to the east or west for the target will be indicated at the end of the output ephemeris." https://ssd.jpl.nasa.gov/horizons/manual.html : 14. Observer sub-longitude & sub-latitude """
454
-
455
- SUB_SOLAR_POSITION: Optional[
456
- Data[
457
- Union[
458
- ZD,
459
- tuple[Time],
460
- tuple[TimeEphemeris],
461
- ],
462
- EllipsoidPosLocationArray,
463
- ]
464
- ]
465
- """ CASA Table cols: Sl_lon, Sl_lat, r. "Heliocentric distance along with "Apparent sub-solar longitude and latitude of the Sun on the target. The apparent planetodetic longitude and latitude of the center of the target disc as seen from the Sun, as seen by the observer at print-time. This is _NOT_ exactly the same as the "sub-solar" (nearest) point for a non-spherical target shape (since the center of the disc seen from the Sun might not be the closest point to the Sun), but is very close if not a highly irregular body shape. Light travel-time from Sun to target and from target to observer is taken into account. Latitude is the angle between the equatorial plane and the line perpendicular to the reference ellipsoid of the body. The reference ellipsoid is an oblate spheroid with a single flatness coefficient in which the y-axis body radius is taken to be the same value as the x-axis radius. Uses IAU2009 rotation models except for Earth and Moon, which uses a higher precision models. Values for Jupiter, Saturn, Uranus and Neptune are Set III, referring to rotation of their magnetic fields. Whether longitude is positive to the east or west for the target will be indicated at the end of the output ephemeris." https://ssd.jpl.nasa.gov/horizons/manual.html : 15. Solar sub-longitude & sub-latitude """
466
-
467
- HELIOCENTRIC_RADIAL_VELOCITY: Optional[
468
- Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityArray]
469
- ]
470
- """ CASA Table cols: rdot."The Sun's apparent range-rate relative to the target, as seen by the observer. A positive "rdot" means the target was moving away from the Sun, negative indicates movement toward the Sun." https://ssd.jpl.nasa.gov/horizons/manual.html : 19. Solar range & range-rate (relative to target) """
471
-
472
- OBSERVER_PHASE_ANGLE: Optional[
473
- Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityArray]
474
- ]
475
- """ CASA Table cols: phang.""phi" is the true PHASE ANGLE at the observers' location at print time. "PAB-LON" and "PAB-LAT" are the FK4/B1950 or ICRF/J2000 ecliptic longitude and latitude of the phase angle bisector direction; the outward directed angle bisecting the arc created by the apparent vector from Sun to target center and the astrometric vector from observer to target center. For an otherwise uniform ellipsoid, the time when its long-axis is perpendicular to the PAB direction approximately corresponds to lightcurve maximum (or maximum brightness) of the body. PAB is discussed in Harris et al., Icarus 57, 251-258 (1984)." https://ssd.jpl.nasa.gov/horizons/manual.html : Phase angle and bisector """
476
-
477
- OBSERVER_POSITION: Optional[Data[ZD, LocationArray]]
478
- """ Observer location. """
479
-
480
- # --- Attributes ---
481
- DOPPLER_SHIFT_VELOCITY: Optional[Attr[numpy.float64]]
482
- """ Velocity definition of the Doppler shift, e.g., RADIO or OPTICAL velocity in m/s """
483
-
484
- source_model_url: Optional[Attr[str]]
485
- """URL to access source model"""
486
- ephemeris_name: Optional[Attr[str]]
487
- """The name of the ephemeris. For example DE430.
488
-
489
- This can be used with Astropy solar_system_ephemeris.set('DE430'), see
490
- https://docs.astropy.org/en/stable/coordinates/solarsystem.html.
491
- """
492
- is_ephemeris: Attr[bool] = False
493
-
494
- type: Attr[str] = "field_and_source"
495
- """
496
- Type of dataset.
497
- """
498
-
499
- # --- Optional coordinates ---
500
- sky_dir_label: Optional[Coord[SkyDirLabel, str]] = ("ra", "dec")
501
- """ Coordinate labels of sky directions (typically shape 2 and 'ra', 'dec') """
502
- sky_pos_label: Optional[Coord[SkyPosLabel, str]] = ("ra", "dec", "dist")
503
- """ Coordinate lables of sky positions (typically shape 3 and 'ra', 'dec', 'dist') """
504
- ellipsoid_pos_label: Optional[Coord[EllipsoidPosLabel, str]] = (
505
- "lon",
506
- "lat",
507
- "height",
508
- )
509
- """ Coordinate labels of geodetic earth location data (typically shape 3 and 'lon', 'lat', 'height')"""
510
- cartesian_pos_label: Optional[Coord[CartesianPosLabel, str]] = ("x", "y", "z")
511
- """ Coordinate labels of geocentric earth location data (typically shape 3 and 'x', 'y', 'z')"""
512
-
513
-
514
- @dict_schema
515
- class PartitionInfoDict:
516
- # spectral_window_id: missing / remove for good?
517
- spectral_window_name: str
518
- """ Spectral window Name """
519
- # field_id: missing / probably remove for good?
520
- field_name: list[str]
521
- """ List of all field names """
522
- polarization_setup: list[str]
523
- """ List of polrization bases. """
524
- scan_number: list[int]
525
- """ List of scan numbers. """
526
- source_name: list[str]
527
- """ List of source names. """
528
- # source_id: mising / remove for good?
529
- intents: list[str]
530
- """ Infromation in obs_mode column of MSv2 State table. """
531
- taql: Optional[str]
532
- """ The taql query used if converted from MSv2. """
533
- line_name: list[str]
534
- """ Spectral line names """
535
-
536
-
537
- @dict_schema
538
- class ObservationInfoDict:
539
- observer: list
540
- """List of observer names."""
541
- project: str
542
- """Project Code/Project_UID"""
543
- release_date: str
544
- """Project release date. This is the date on which the data may become
545
- public. Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
546
- execution_block_id: Optional[str]
547
- """ ASDM: Indicates the position of the execution block in the project
548
- (sequential numbering starting at 1). """
549
- execution_block_number: Optional[int]
550
- """ASDM: Indicates the position of the execution block in the project
551
- (sequential numbering starting at 1)."""
552
- execution_block_UID: Optional[str]
553
- """ASDM: The archive’s UID of the execution block."""
554
- session_reference: Optional[str]
555
- """ASDM: The observing session reference."""
556
- observing_script: Optional[str]
557
- """ASDM: The text of the observation script."""
558
- observing_script_UID: Optional[str]
559
- """ASDM: A reference to the Entity which contains the observing script."""
560
- observing_log: Optional[str]
561
- """ASDM: Logs of the observation during this execu- tion block."""
562
-
563
-
564
- @dict_schema
565
- class ProcessorInfoDict:
566
- type: str
567
- """Processor type; reserved keywords include (”CORRELATOR” -
568
- interferometric correlator; ”SPECTROMETER” - single-dish correlator;
569
- ”RADIOMETER” - generic detector/integrator)."""
570
- sub_type: str
571
- """Processor sub-type, e.g. ”GBT” or ”JIVE”."""
572
-
573
-
574
- @xarray_dataarray_schema
575
- class BaselineArray:
576
- """TODO: documentation"""
577
-
578
- data: Data[BaselineId, Union[numpy.int64, numpy.int32]]
579
- """Unique id for each baseline."""
580
- long_name: Optional[Attr[str]] = "Baseline ID"
581
-
582
-
583
- @xarray_dataarray_schema
584
- class BaselineAntennaNameArray:
585
- """Array of antenna_name by baseline_id, as used in main_xds and main_sd_xds
586
- (antenna_name by baseline_id dim"""
587
-
588
- data: Data[BaselineId, str]
589
- """Unique id for each baseline."""
590
- long_name: Optional[Attr[str]] = "Antenna name by baseline_id"
591
-
592
-
593
- @xarray_dataarray_schema
594
- class AntennaNameArray:
595
- """TODO: documentation"""
596
-
597
- data: Data[AntennaName, str]
598
- """Unique name for each antenna(_station)."""
599
- long_name: Optional[Attr[str]] = "Antenna name"
600
-
601
-
602
- @xarray_dataset_schema
603
- class DopplerXds:
604
- """Not specified. Not implemented."""
605
-
606
- pass
607
-
608
657
 
609
658
  @xarray_dataarray_schema
610
659
  class FrequencyArray:
611
- """TODO: documentation"""
660
+ """Frequency coordinate in the main dataset."""
612
661
 
613
662
  data: Data[Frequency, float]
614
663
  """ Time, expressed in SI seconds since the epoch. """
@@ -621,18 +670,20 @@ class FrequencyArray:
621
670
  frequency corresponding to the DC edge of the baseband. Used by the calibration
622
671
  system if a fixed scaling frequency is required or in algorithms to identify the
623
672
  observing band. """
624
- channel_width: Attr[QuantityArray] # Not SpectralCoord, as it is a difference
673
+ channel_width: Attr[
674
+ QuantityInHertzArray
675
+ ] # Not SpectralCoord, as it is a difference
625
676
  """ The nominal channel bandwidth. Same units as data array (see units key). """
626
- doppler: Optional[Attr[DopplerXds]]
677
+ doppler: Optional[Attr[DopplerArray]]
627
678
  """ Doppler tracking information """
628
679
 
629
- type: Attr[str] = "spectral_coord"
680
+ type: Attr[SpectralCoord] = "spectral_coord"
630
681
  """ Coordinate type. Should be ``"spectral_coord"``. """
631
682
  long_name: Optional[Attr[str]] = "Frequency"
632
683
  """ Long-form name to use for axis"""
633
- units: Attr[list[str]] = ("Hz",)
684
+ units: Attr[UnitsHertz] = ("Hz",)
634
685
  """ Units to associate with axis"""
635
- frame: Attr[str] = "icrs"
686
+ observer: Attr[AllowedSpectralCoordFrames] = "icrs"
636
687
  """
637
688
  Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
638
689
  Note that Astropy does not use the name
@@ -648,16 +699,19 @@ class FrequencyCalArray:
648
699
 
649
700
  data: Data[FrequencyCal, float]
650
701
  """ Time, expressed in SI seconds since the epoch. """
651
- reference_value: Attr[SpectralCoordArray]
652
- """ A frequency representative of the spectral window, usually the sky
653
- frequency corresponding to the DC edge of the baseband. Used by the calibration
654
- system if a fixed scaling frequency is required or in algorithms to identify the
655
- observing band. """
656
702
 
657
- type: Attr[str] = "spectral_coord"
658
- units: Attr[list[str]] = ("Hz",)
703
+ type: Attr[SpectralCoord] = "spectral_coord"
704
+ units: Attr[UnitsHertz] = ("Hz",)
659
705
  """ Units to associate with axis"""
660
706
 
707
+ observer: Attr[AllowedSpectralCoordFrames] = "icrs"
708
+ """
709
+ Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
710
+ Note that Astropy does not use the name
711
+ 'topo' (telescope centric) velocity frame, rather it assumes if no velocity
712
+ frame is given that this is the default.
713
+ """
714
+
661
715
 
662
716
  @xarray_dataarray_schema
663
717
  class PolarizationArray:
@@ -700,75 +754,37 @@ class UvwLabelArray:
700
754
 
701
755
  # Data variables
702
756
  @xarray_dataarray_schema
703
- class VisibilityArray:
704
- """TODO: documentation"""
757
+ class FlagArray:
758
+ """
759
+ An array of Boolean values with the same shape as `VISIBILITY`,
760
+ representing the cumulative flags applying to this data matrix. Data are
761
+ flagged bad if the ``FLAG`` array element is ``True``.
762
+ """
705
763
 
706
764
  data: Data[
707
- tuple[Time, BaselineId, Frequency, Polarization],
708
- Union[numpy.complex64, numpy.complex128],
765
+ Union[
766
+ tuple[Time, BaselineId, Frequency, Polarization],
767
+ tuple[Time, BaselineId, Frequency],
768
+ tuple[Time, BaselineId],
769
+ tuple[Time, AntennaName, Frequency, Polarization], # SD
770
+ ],
771
+ bool,
709
772
  ]
710
-
711
773
  time: Coordof[TimeCoordArray]
712
- baseline_id: Coordof[BaselineArray]
713
- polarization: Coordof[PolarizationArray]
774
+ baseline_id: Optional[Coordof[BaselineArray]] # Only IF
775
+ antenna_name: Optional[Coordof[AntennaNameArray]] # Only SD
714
776
  frequency: Coordof[FrequencyArray]
777
+ polarization: Optional[Coordof[PolarizationArray]] = None
778
+ long_name: Optional[Attr[str]] = "Visibility flags"
715
779
 
716
- field_and_source_xds: Attr[FieldSourceXds]
717
- long_name: Optional[Attr[str]] = "Visibility values"
718
- """ Long-form name to use for axis. Should be ``"Visibility values"``"""
719
- units: Attr[list[str]] = ("Jy",)
780
+ allow_mutiple_versions: Optional[Attr[bool]] = True
720
781
 
721
782
 
722
783
  @xarray_dataarray_schema
723
- class SpectrumArray:
724
- """Definition of xr.DataArray for SPECTRUM data (single dish)"""
725
-
726
- data: Data[
727
- tuple[Time, AntennaName, Frequency, Polarization],
728
- Union[numpy.float64, numpy.float32, numpy.float16],
729
- ]
730
-
731
- time: Coordof[TimeCoordArray]
732
- antenna_name: Coordof[AntennaNameArray]
733
- frequency: Coordof[FrequencyArray]
734
- polarization: Coordof[PolarizationArray]
735
-
736
- field_and_source_xds: Attr[FieldSourceXds]
737
- long_name: Optional[Attr[str]] = "Spectrum values"
738
- """ Long-form name to use for axis. Should be ``"Spectrum values"``"""
739
- units: Attr[list[str]] = ("Jy",)
740
-
741
-
742
- @xarray_dataarray_schema
743
- class FlagArray:
744
- """
745
- An array of Boolean values with the same shape as `VISIBILITY`,
746
- representing the cumulative flags applying to this data matrix. Data are
747
- flagged bad if the ``FLAG`` array element is ``True``.
748
- """
749
-
750
- data: Data[
751
- Union[
752
- tuple[Time, BaselineId, Frequency, Polarization],
753
- tuple[Time, BaselineId, Frequency],
754
- tuple[Time, BaselineId],
755
- tuple[Time, AntennaName, Frequency, Polarization], # SD
756
- ],
757
- bool,
758
- ]
759
- time: Coordof[TimeCoordArray]
760
- baseline_id: Optional[Coordof[BaselineArray]] # Only IF
761
- antenna_name: Optional[Coordof[AntennaNameArray]] # Only SD
762
- frequency: Coordof[FrequencyArray]
763
- polarization: Optional[Coordof[PolarizationArray]] = None
764
- long_name: Optional[Attr[str]] = "Visibility flags"
765
-
766
-
767
- @xarray_dataarray_schema
768
- class WeightArray:
769
- """
770
- The weight for each channel, with the same shape as the associated
771
- :py:class:`VisibilityArray`, as assigned by the correlator or processor.
784
+ class WeightArray:
785
+ """
786
+ The weight for each channel, with the same shape as the associated
787
+ :py:class:`VisibilityArray`, as assigned by the correlator or processor.
772
788
 
773
789
  Weight spectrum in ms v2 is renamed weight. Should be calculated as
774
790
  1/sigma^2 (sigma rms noise).
@@ -787,10 +803,21 @@ class WeightArray:
787
803
  time: Coordof[TimeCoordArray]
788
804
  baseline_id: Optional[Coordof[BaselineArray]] # Only IF
789
805
  antenna_name: Optional[Coordof[AntennaNameArray]] # Only SD
790
- frequency: Optional[Coordof[FrequencyArray]] = None
806
+ frequency: Coordof[FrequencyArray] = None
791
807
  polarization: Optional[Coordof[PolarizationArray]] = None
792
808
  long_name: Optional[Attr[str]] = "Visibility weights"
793
809
 
810
+ allow_mutiple_versions: Optional[Attr[bool]] = True
811
+
812
+
813
+ # J2000=>fk5 is used most often. icrs is used less often. Both fk5 and icrs are also borrowed from the field center (to fix
814
+ # ITRF=>J2000). APP has only been seen in WSRT datasets.
815
+ AllowedUvwFrames = Literal[
816
+ "fk5",
817
+ "icrs",
818
+ "APP", # "apparent geocentric position", used in WSRT datasets
819
+ ]
820
+
794
821
 
795
822
  @xarray_dataarray_schema
796
823
  class UvwArray:
@@ -823,14 +850,7 @@ class UvwArray:
823
850
  """
824
851
 
825
852
  data: Data[
826
- Union[
827
- tuple[Time, BaselineId, Frequency, Polarization, UvwLabel],
828
- tuple[Time, BaselineId, Frequency, UvwLabel],
829
- tuple[Time, BaselineId, UvwLabel],
830
- tuple[Time, AntennaName, UvwLabel], # SD
831
- tuple[Time, AntennaName, Frequency, UvwLabel], # SD
832
- tuple[Time, AntennaName, Frequency, Polarization], # SD
833
- ],
853
+ Union[tuple[Time, BaselineId, UvwLabel]],
834
854
  Union[
835
855
  numpy.float16,
836
856
  numpy.float32,
@@ -839,24 +859,29 @@ class UvwArray:
839
859
  ]
840
860
  """Baseline coordinates from ``baseline_antenna2_id`` to ``baseline_antenna1_id``"""
841
861
  time: Coordof[TimeCoordArray]
842
- baseline_id: Optional[Coordof[BaselineArray]] # Only IF
843
- antenna_name: Optional[Coordof[AntennaNameArray]] # Only SD
844
- frequency: Optional[Coordof[FrequencyArray]] = None
845
- polarization: Optional[Coordof[PolarizationArray]] = None
862
+ baseline_id: Optional[Coordof[BaselineArray]]
846
863
  uvw_label: Coordof[UvwLabelArray] = ("u", "v", "w")
864
+
847
865
  long_name: Optional[Attr[str]] = "Baseline coordinates"
848
866
  """ Long-form name to use for axis. Should be ``"Baseline coordinates``"""
849
- units: Attr[list[str]] = ("m",)
867
+
868
+ type: Attr[Literal["uvw"]] = "uvw"
869
+ frame: Attr[AllowedUvwFrames] = "icrs"
870
+ """ To be defined in astropy (see for example https://github.com/astropy/astropy/issues/7766) """
871
+ units: Attr[UnitsMeters] = ("m",)
872
+
873
+ allow_mutiple_versions: Optional[Attr[bool]] = True
850
874
 
851
875
 
852
876
  @xarray_dataarray_schema
853
877
  class TimeSamplingArray:
854
- """TODO: documentation"""
878
+ """
879
+ Model of arrays of measures used in the main dataset for data variables such as TIME_CENTROID and
880
+ TIME_CENTROID_EXTRA_PRECISION.
881
+ """
855
882
 
856
883
  data: Data[
857
884
  Union[
858
- tuple[Time, BaselineId, Frequency, Polarization],
859
- tuple[Time, BaselineId, Frequency],
860
885
  tuple[Time, BaselineId],
861
886
  tuple[Time, AntennaName], # SD
862
887
  ],
@@ -866,49 +891,345 @@ class TimeSamplingArray:
866
891
  time: Coordof[TimeCoordArray]
867
892
  baseline_id: Optional[Coordof[BaselineArray]] # Only IF
868
893
  antenna_name: Optional[Coordof[AntennaNameArray]] # Only SD
869
- frequency: Optional[Coordof[FrequencyArray]] = None
870
- polarization: Optional[Coordof[PolarizationArray]] = None
871
894
 
872
- scale: Attr[str] = "tai"
895
+ scale: Attr[AllowedTimeScales] = "utc"
873
896
  """ Astropy time scales, see :py:class:`astropy.time.Time` """
874
- format: Attr[str] = "unix"
897
+ format: Attr[AllowedTimeFormats] = "unix"
875
898
  """ Astropy format, see :py:class:`astropy.time.Time`. Default seconds from 1970-01-01 00:00:00 UTC """
876
899
 
877
900
  long_name: Optional[Attr[str]] = "Time sampling data"
878
- units: Attr[list[str]] = ("s",)
901
+ units: Attr[UnitsSeconds] = ("s",)
902
+
903
+
904
+ @xarray_dataarray_schema
905
+ class FreqSamplingArray:
906
+ """
907
+ Model of frequency related data variables of the main dataset, such as EFFECTIV_CHANNEL_WIDTH and FREQUENCY_CENTROID.
908
+ """
909
+
910
+ data: Data[
911
+ Union[
912
+ tuple[Time, BaselineId, Frequency, Polarization],
913
+ tuple[Time, BaselineId, Frequency],
914
+ tuple[Time, Frequency],
915
+ tuple[Frequency],
916
+ ],
917
+ float,
918
+ ]
919
+ """
920
+ Data about frequency sampling, such as centroid or integration
921
+ time. Concrete function depends on concrete data array within
922
+ :py:class:`VisibilityXds` or :py:class:`SpectrumXds`.
923
+ """
924
+ frequency: Coordof[FrequencyArray]
925
+ time: Optional[Coordof[TimeCoordArray]] = None
926
+ baseline_id: Optional[Coordof[BaselineArray]] = None
927
+ polarization: Optional[Coordof[PolarizationArray]] = None
928
+ long_name: Optional[Attr[str]] = "Frequency sampling data"
929
+ units: Attr[UnitsHertz] = ("Hz",)
930
+ observer: Attr[AllowedSpectralCoordFrames] = "icrs"
931
+ """
932
+ Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
933
+ Note that Astropy does not use the name
934
+ 'topo' (telescope centric) velocity frame, rather it assumes if no velocity
935
+ frame is given that this is the default.
936
+ """
937
+
938
+
939
+ # Define FieldAndSourceXds dataset already here, as it is needed in the
940
+ # definition of VisibilityArray
941
+ @xarray_dataset_schema
942
+ class FieldSourceXds:
943
+ """
944
+ Field positions for each source.
945
+
946
+ Defines a field position on the sky. For interferometers, this is the correlated field position.
947
+ For single dishes, this is the nominal pointing direction.
948
+ """
949
+
950
+ source_name: Optional[Coord[Union[ZD, Time], str]]
951
+ """ Source name. """
952
+ field_name: Optional[Coord[Union[ZD, Time], str]]
953
+ """Field name."""
954
+
955
+ time: Optional[Coordof[TimeInterpolatedCoordArray]]
956
+ """Midpoint of time for which this set of parameters is accurate. Labeled 'time' when interpolated to main time """
957
+ time_ephemeris: Optional[Coordof[TimeEphemerisCoordArray]]
958
+ """Midpoint of time for which this set of parameters is accurate. Labeled 'time_ephemeris' when not interpolating to main time """
959
+
960
+ line_label: Optional[Coord[LineLabel, str]]
961
+ """ Line labels (for line names and variables). """
962
+
963
+ line_names: Optional[
964
+ Coord[
965
+ Union[
966
+ tuple[LineLabel],
967
+ tuple[Time, LineLabel],
968
+ tuple[TimeEphemeris, LineLabel],
969
+ ],
970
+ str,
971
+ ]
972
+ ]
973
+ """ Line names (e.g. v=1, J=1-0, SiO). """
974
+
975
+ FIELD_PHASE_CENTER: Optional[
976
+ Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], SkyCoordArray]
977
+ ]
978
+ """
979
+ Offset from the SOURCE_DIRECTION that gives the direction of phase
980
+ center for which the fringes have been stopped-that is a point source in
981
+ this direction will produce a constant measured phase (page 2 of
982
+ https://articles.adsabs.harvard.edu/pdf/1999ASPC..180...79F). For
983
+ conversion from MSv2, frame refers column keywords by default. If frame
984
+ varies with field, it refers DelayDir_Ref column instead.
985
+ """
986
+
987
+ FIELD_REFERENCE_CENTER: Optional[
988
+ Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], SkyCoordArray]
989
+ ]
990
+ """
991
+ Used in single-dish to record the associated reference direction if positionswitching
992
+ been applied. For conversion from MSv2, frame refers column keywords by default. If
993
+ frame varies with field, it refers DelayDir_Ref column instead.
994
+ """
995
+
996
+ SOURCE_LOCATION: Optional[
997
+ Data[
998
+ Union[
999
+ ZD,
1000
+ tuple[Time],
1001
+ tuple[TimeEphemeris],
1002
+ ],
1003
+ SkyCoordArray,
1004
+ ]
1005
+ ]
1006
+ """
1007
+ CASA Table Cols: RA,DEC,Rho."Astrometric RA and Dec and Geocentric
1008
+ distance with respect to the observer’s location (Geocentric). "Adjusted
1009
+ for light-time aberration only. With respect to the reference plane and
1010
+ equinox of the chosen system (ICRF or FK4/B1950). If the FK4/B1950 frame
1011
+ output is selected, elliptic aberration terms are added. Astrometric RA/DEC
1012
+ is generally used when comparing or reducing data against a star catalog."
1013
+ https://ssd.jpl.nasa.gov/horizons/manual.html : 1. Astrometric RA & DEC
1014
+ """
1015
+
1016
+ LINE_REST_FREQUENCY: Optional[
1017
+ Data[
1018
+ Union[
1019
+ tuple[LineLabel],
1020
+ tuple[Time, LineLabel],
1021
+ tuple[TimeEphemeris, LineLabel],
1022
+ ],
1023
+ SpectralCoordArray,
1024
+ ]
1025
+ ]
1026
+ """ Rest frequencies for the transitions. """
879
1027
 
1028
+ LINE_SYSTEMIC_VELOCITY: Optional[
1029
+ Data[
1030
+ Union[
1031
+ tuple[LineLabel],
1032
+ tuple[Time, LineLabel],
1033
+ tuple[TimeEphemeris, LineLabel],
1034
+ ],
1035
+ QuantityInMetersPerSecondArray,
1036
+ ]
1037
+ ]
1038
+ """ Systemic velocity at reference """
1039
+
1040
+ SOURCE_RADIAL_VELOCITY: Optional[
1041
+ Data[
1042
+ Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityInMetersPerSecondArray
1043
+ ]
1044
+ ]
1045
+ """ CASA Table Cols: RadVel. Geocentric distance rate """
1046
+
1047
+ NORTH_POLE_POSITION_ANGLE: Optional[
1048
+ Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityInRadiansArray]
1049
+ ]
1050
+ """ CASA Table cols: NP_ang, "Targets' apparent north-pole position angle (counter-clockwise with respect to direction of true-of-date reference-frame north pole) and angular distance from the sub-observer point (center of disc) at print time. A negative distance indicates the north-pole is on the hidden hemisphere." https://ssd.jpl.nasa.gov/horizons/manual.html : 17. North pole position angle & distance from disc center. """
1051
+
1052
+ NORTH_POLE_ANGULAR_DISTANCE: Optional[
1053
+ Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityInRadiansArray]
1054
+ ]
1055
+ """ CASA Table cols: NP_dist, "Targets' apparent north-pole position angle (counter-clockwise with respect to direction of true-of date reference-frame north pole) and angular distance from the sub-observer point (center of disc) at print time. A negative distance indicates the north-pole is on the hidden hemisphere."https://ssd.jpl.nasa.gov/horizons/manual.html : 17. North pole position angle & distance from disc center. """
1056
+
1057
+ SUB_OBSERVER_DIRECTION: Optional[
1058
+ Data[
1059
+ Union[
1060
+ ZD,
1061
+ tuple[Time],
1062
+ tuple[TimeEphemeris],
1063
+ ],
1064
+ EllipsoidPosLocationArray,
1065
+ ]
1066
+ ]
1067
+ """ CASA Table cols: DiskLong, DiskLat. "Apparent planetodetic longitude and latitude of the center of the target disc seen by the OBSERVER at print-time. This is not exactly the same as the "nearest point" for a non-spherical target shape (since the center of the disc might not be the point closest to the observer), but is generally very close if not a very irregular body shape. The IAU2009 rotation models are used except for Earth and MOON, which use higher-precision models. For the gas giants Jupiter, Saturn, Uranus and Neptune, IAU2009 longitude is based on the "System III" prime meridian rotation angle of the magnetic field. By contrast, pole direction (thus latitude) is relative to the body dynamical equator. There can be an offset between the magnetic pole and the dynamical pole of rotation. Down-leg light travel-time from target to observer is taken into account. Latitude is the angle between the equatorial plane and perpendicular to the reference ellipsoid of the body and body oblateness thereby included. The reference ellipsoid is an oblate spheroid with a single flatness coefficient in which the y-axis body radius is taken to be the same value as the x-axis radius. Whether longitude is positive to the east or west for the target will be indicated at the end of the output ephemeris." https://ssd.jpl.nasa.gov/horizons/manual.html : 14. Observer sub-longitude & sub-latitude """
1068
+
1069
+ SUB_SOLAR_POSITION: Optional[
1070
+ Data[
1071
+ Union[
1072
+ ZD,
1073
+ tuple[Time],
1074
+ tuple[TimeEphemeris],
1075
+ ],
1076
+ EllipsoidPosLocationArray,
1077
+ ]
1078
+ ]
1079
+ """ CASA Table cols: Sl_lon, Sl_lat, r. "Heliocentric distance along with "Apparent sub-solar longitude and latitude of the Sun on the target. The apparent planetodetic longitude and latitude of the center of the target disc as seen from the Sun, as seen by the observer at print-time. This is _NOT_ exactly the same as the "sub-solar" (nearest) point for a non-spherical target shape (since the center of the disc seen from the Sun might not be the closest point to the Sun), but is very close if not a highly irregular body shape. Light travel-time from Sun to target and from target to observer is taken into account. Latitude is the angle between the equatorial plane and the line perpendicular to the reference ellipsoid of the body. The reference ellipsoid is an oblate spheroid with a single flatness coefficient in which the y-axis body radius is taken to be the same value as the x-axis radius. Uses IAU2009 rotation models except for Earth and Moon, which uses a higher precision models. Values for Jupiter, Saturn, Uranus and Neptune are Set III, referring to rotation of their magnetic fields. Whether longitude is positive to the east or west for the target will be indicated at the end of the output ephemeris." https://ssd.jpl.nasa.gov/horizons/manual.html : 15. Solar sub-longitude & sub-latitude """
1080
+
1081
+ HELIOCENTRIC_RADIAL_VELOCITY: Optional[
1082
+ Data[
1083
+ Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityInMetersPerSecondArray
1084
+ ]
1085
+ ]
1086
+ """ CASA Table cols: rdot."The Sun's apparent range-rate relative to the target, as seen by the observer. A positive "rdot" means the target was moving away from the Sun, negative indicates movement toward the Sun." https://ssd.jpl.nasa.gov/horizons/manual.html : 19. Solar range & range-rate (relative to target) """
1087
+
1088
+ OBSERVER_PHASE_ANGLE: Optional[
1089
+ Data[Union[ZD, tuple[Time], tuple[TimeEphemeris]], QuantityInRadiansArray]
1090
+ ]
1091
+ """ CASA Table cols: phang.""phi" is the true PHASE ANGLE at the observers' location at print time. "PAB-LON" and "PAB-LAT" are the FK4/B1950 or ICRF/J2000 ecliptic longitude and latitude of the phase angle bisector direction; the outward directed angle bisecting the arc created by the apparent vector from Sun to target center and the astrometric vector from observer to target center. For an otherwise uniform ellipsoid, the time when its long-axis is perpendicular to the PAB direction approximately corresponds to lightcurve maximum (or maximum brightness) of the body. PAB is discussed in Harris et al., Icarus 57, 251-258 (1984)." https://ssd.jpl.nasa.gov/horizons/manual.html : Phase angle and bisector """
1092
+
1093
+ OBSERVER_POSITION: Optional[Data[ZD, LocationArray]]
1094
+ """ Observer location. """
1095
+
1096
+ # --- Attributes ---
1097
+ doppler_shift_velocity: Optional[Attr[UnitsOfDopplerShift]]
1098
+ """ Velocity definition of the Doppler shift, e.g., RADIO or OPTICAL velocity in m/s """
1099
+
1100
+ source_model_url: Optional[Attr[str]]
1101
+ """URL to access source model"""
1102
+ ephemeris_name: Optional[Attr[str]]
1103
+ """The name of the ephemeris. For example DE430.
1104
+
1105
+ This can be used with Astropy solar_system_ephemeris.set('DE430'), see
1106
+ https://docs.astropy.org/en/stable/coordinates/solarsystem.html.
1107
+ """
1108
+ is_ephemeris: Attr[bool] = False
1109
+
1110
+ type: Attr[Literal["field_and_source"]] = "field_and_source"
1111
+ """
1112
+ Type of dataset.
1113
+ """
1114
+
1115
+ # --- Optional coordinates ---
1116
+ sky_dir_label: Optional[Coord[SkyDirLabel, str]] = ("ra", "dec")
1117
+ """ Coordinate labels of sky directions (typically shape 2 and 'ra', 'dec') """
1118
+ sky_pos_label: Optional[Coord[SkyPosLabel, str]] = ("ra", "dec", "dist")
1119
+ """ Coordinate lables of sky positions (typically shape 3 and 'ra', 'dec', 'dist') """
1120
+ ellipsoid_pos_label: Optional[Coord[EllipsoidPosLabel, str]] = (
1121
+ "lon",
1122
+ "lat",
1123
+ "height",
1124
+ )
1125
+ """ Coordinate labels of geodetic earth location data (typically shape 3 and 'lon', 'lat', 'height')"""
1126
+ cartesian_pos_label: Optional[Coord[CartesianPosLabel, str]] = ("x", "y", "z")
1127
+ """ Coordinate labels of geocentric earth location data (typically shape 3 and 'x', 'y', 'z')"""
1128
+
1129
+
1130
+ @xarray_dataarray_schema
1131
+ class SpectrumArray:
1132
+ """Definition of xr.DataArray for SPECTRUM data (single dish)"""
1133
+
1134
+ data: Data[
1135
+ tuple[Time, AntennaName, Frequency, Polarization],
1136
+ Union[numpy.float64, numpy.float32, numpy.float16],
1137
+ ]
1138
+
1139
+ time: Coordof[TimeCoordArray]
1140
+ antenna_name: Coordof[AntennaNameArray]
1141
+ frequency: Coordof[FrequencyArray]
1142
+ polarization: Coordof[PolarizationArray]
1143
+
1144
+ field_and_source_xds: Attr[FieldSourceXds]
1145
+ long_name: Optional[Attr[str]] = "Spectrum values"
1146
+ """ Long-form name to use for axis. Should be ``"Spectrum values"``"""
1147
+ units: Attr[list[str]] = ("Jy",)
1148
+
1149
+
1150
+ @xarray_dataarray_schema
1151
+ class VisibilityArray:
1152
+ """Visibility data array in main dataset (interferometric data, :py:class:`VisibiiltyXds`)"""
1153
+
1154
+ data: Data[
1155
+ tuple[Time, BaselineId, Frequency, Polarization],
1156
+ Union[numpy.complex64, numpy.complex128],
1157
+ ]
1158
+
1159
+ time: Coordof[TimeCoordArray]
1160
+ baseline_id: Coordof[BaselineArray]
1161
+ polarization: Coordof[PolarizationArray]
1162
+ frequency: Coordof[FrequencyArray]
1163
+
1164
+ field_and_source_xds: Attr[FieldSourceXds]
1165
+ long_name: Optional[Attr[str]] = "Visibility values"
1166
+ """ Long-form name to use for axis. Should be ``"Visibility values"``"""
1167
+ units: Attr[list[str]] = ("Jy",)
1168
+
1169
+ allow_mutiple_versions: Optional[Attr[bool]] = True
1170
+
1171
+
1172
+ # Info dicts
1173
+
1174
+
1175
+ @dict_schema
1176
+ class PartitionInfoDict:
1177
+ # spectral_window_id: missing / remove for good?
1178
+ spectral_window_name: str
1179
+ """ Spectral window Name """
1180
+ # field_id: missing / probably remove for good?
1181
+ field_name: list[str]
1182
+ """ List of all field names """
1183
+ polarization_setup: list[str]
1184
+ """ List of polrization bases. """
1185
+ scan_number: list[int]
1186
+ """ List of scan numbers. """
1187
+ source_name: list[str]
1188
+ """ List of source names. """
1189
+ # source_id: mising / remove for good?
1190
+ intents: list[str]
1191
+ """ Infromation in obs_mode column of MSv2 State table. """
1192
+ taql: Optional[str]
1193
+ """ The taql query used if converted from MSv2. """
1194
+ line_name: list[str]
1195
+ """ Spectral line names """
1196
+
1197
+
1198
+ @dict_schema
1199
+ class ObservationInfoDict:
1200
+ observer: list
1201
+ """List of observer names."""
1202
+ project: str
1203
+ """Project Code/Project_UID"""
1204
+ release_date: str
1205
+ """Project release date. This is the date on which the data may become
1206
+ public. Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
1207
+ execution_block_id: Optional[str]
1208
+ """ ASDM: Indicates the position of the execution block in the project
1209
+ (sequential numbering starting at 1). """
1210
+ execution_block_number: Optional[int]
1211
+ """ASDM: Indicates the position of the execution block in the project
1212
+ (sequential numbering starting at 1)."""
1213
+ execution_block_UID: Optional[str]
1214
+ """ASDM: The archive’s UID of the execution block."""
1215
+ session_reference: Optional[str]
1216
+ """ASDM: The observing session reference."""
1217
+ observing_script: Optional[str]
1218
+ """ASDM: The text of the observation script."""
1219
+ observing_script_UID: Optional[str]
1220
+ """ASDM: A reference to the Entity which contains the observing script."""
1221
+ observing_log: Optional[str]
1222
+ """ASDM: Logs of the observation during this execu- tion block."""
880
1223
 
881
- @xarray_dataarray_schema
882
- class FreqSamplingArray:
883
- """TODO: documentation"""
884
1224
 
885
- data: Data[
886
- Union[
887
- tuple[Time, BaselineId, Frequency, Polarization],
888
- tuple[Time, BaselineId, Frequency],
889
- tuple[Time, Frequency],
890
- tuple[Frequency],
891
- ],
892
- float,
893
- ]
894
- """
895
- Data about frequency sampling, such as centroid or integration
896
- time. Concrete function depends on concrete data array within
897
- :py:class:`VisibilityXds`.
898
- """
899
- frequency: Coordof[FrequencyArray]
900
- time: Optional[Coordof[TimeCoordArray]] = None
901
- baseline_id: Optional[Coordof[BaselineArray]] = None
902
- polarization: Optional[Coordof[PolarizationArray]] = None
903
- long_name: Optional[Attr[str]] = "Frequency sampling data"
904
- units: Attr[list[str]] = ("Hz",)
905
- frame: Attr[str] = "icrs"
906
- """
907
- Astropy velocity reference frames (see :external:ref:`astropy-spectralcoord`).
908
- Note that Astropy does not use the name
909
- 'topo' (telescope centric) velocity frame, rather it assumes if no velocity
910
- frame is given that this is the default.
911
- """
1225
+ @dict_schema
1226
+ class ProcessorInfoDict:
1227
+ type: str
1228
+ """Processor type; reserved keywords include (”CORRELATOR” -
1229
+ interferometric correlator; ”SPECTROMETER” - single-dish correlator;
1230
+ ”RADIOMETER” - generic detector/integrator)."""
1231
+ sub_type: str
1232
+ """Processor sub-type, e.g. ”GBT” or ”JIVE”."""
912
1233
 
913
1234
 
914
1235
  # Data Sets
@@ -916,6 +1237,10 @@ class FreqSamplingArray:
916
1237
 
917
1238
  @xarray_dataset_schema
918
1239
  class AntennaXds:
1240
+ """
1241
+ Antenna dataset: global antenna properties for each antenna.
1242
+ """
1243
+
919
1244
  # Coordinates
920
1245
  antenna_name: Coordof[AntennaNameArray]
921
1246
  """ Antenna name """
@@ -931,11 +1256,9 @@ class AntennaXds:
931
1256
  ”SPACE-HALCA” - specific orientation model."""
932
1257
  telescope_name: Coord[AntennaName, str]
933
1258
  """ Useful when data is combined from mutiple arrays for example ACA + ALMA. """
934
- # TODO: receptor_label, polarization_type, sky_dir_label set as optional
935
- # for datasets like test_alma_ephemris_mosaic. See also BEAM_OFFSET below.
936
- receptor_label: Optional[Coord[ReceptorLabel, str]]
1259
+ receptor_label: Coord[ReceptorLabel, str]
937
1260
  """ Names of receptors """
938
- polarization_type: Optional[Coord[tuple[AntennaName, ReceptorLabel], str]]
1261
+ polarization_type: Coord[tuple[AntennaName, ReceptorLabel], str]
939
1262
  """ Polarization type to which each receptor responds (e.g. ”R”,”L”,”X” or ”Y”).
940
1263
  This is the receptor polarization type as recorded in the final correlated data (e.g. ”RR”); i.e.
941
1264
  as measured after all polarization combiners. ['X','Y'], ['R','L'] """
@@ -943,50 +1266,36 @@ class AntennaXds:
943
1266
  """ (x,y,z) - either cartesian or ellipsoid """
944
1267
  ellipsoid_pos_label: Optional[Coord[EllipsoidPosLabel, str]]
945
1268
  """ (lon, lat, dist) - either cartesian or ellipsoid"""
946
- sky_dir_label: Optional[Coord[SkyDirLabel, str]]
947
- """ ra, dec """
948
1269
 
949
1270
  # Data variables
950
- ANTENNA_POSITION: Data[
951
- Union[
952
- tuple[AntennaName, EllipsoidPosLabel], tuple[AntennaName, CartesianPosLabel]
953
- ],
954
- QuantityArray,
955
- ] # EarthLocationArray
1271
+ ANTENNA_POSITION: Data[tuple[AntennaName], LocationArray]
956
1272
  """
957
1273
  In a right-handed frame, X towards the intersection of the equator and
958
1274
  the Greenwich meridian, Z towards the pole.
959
1275
  """
960
- ANTENNA_FEED_OFFSET: Data[
961
- Union[
962
- tuple[AntennaName, EllipsoidPosLabel], tuple[AntennaName, CartesianPosLabel]
963
- ],
964
- QuantityArray,
965
- ]
966
- """
967
- Offset of feed relative to position (``Antenna_Table.offset + Feed_Table.position``).
968
- """
969
- ANTENNA_DISH_DIAMETER: Optional[Data[tuple[AntennaName], QuantityArray]]
1276
+ ANTENNA_DISH_DIAMETER: Optional[Data[tuple[AntennaName], QuantityInMetersArray]]
970
1277
  """
971
- Nominal diameter of dish, as opposed to the effective diameter.
1278
+ The diameter of the main reflector (or the largest dimension for non-circular apertures).
972
1279
  """
973
1280
  ANTENNA_EFFECTIVE_DISH_DIAMETER: Optional[
974
- Data[tuple[AntennaName, ReceptorLabel, SkyDirLabel], QuantityArray]
1281
+ Data[tuple[AntennaName], QuantityInMetersArray]
975
1282
  ]
976
- """ Airy Disk Model .... """
1283
+ """ Effective dish diameter used in computing beam model (such as airy disk). """
977
1284
 
978
- # TODO: setting BEAM_OFFSET and RECEPTOR_ANGLE as optional for now, as it
979
- # is not present in some datasets (example: test_alma_ephemris_mosaic)
980
- BEAM_OFFSET: Optional[Data[tuple[AntennaName, ReceptorLabel], SkyCoordArray]]
1285
+ ANTENNA_BLOCKAGE: Optional[Data[tuple[AntennaName], QuantityInMetersArray]]
981
1286
  """
982
- Beam position offset, as defined on the sky but in the antenna
983
- reference frame.
1287
+ Blockage caused by secondary reflector used in computing beam model (such as airy disk).
984
1288
  """
985
- RECEPTOR_ANGLE: Optional[Data[tuple[AntennaName, ReceptorLabel], QuantityArray]]
1289
+
1290
+ # TODO: setting BEAM_OFFSET and RECEPTOR_ANGLE as optional for now, as it
1291
+ # is not present in some datasets (example: test_alma_ephemris_mosaic)
1292
+ ANTENNA_RECEPTOR_ANGLE: Optional[
1293
+ Data[tuple[AntennaName, ReceptorLabel], QuantityInRadiansArray]
1294
+ ]
986
1295
  """
987
1296
  Polarization reference angle. Converts into parallactic angle in the sky domain.
988
1297
  """
989
- FOCUS_LENGTH: Optional[Data[tuple[AntennaName], QuantityArray]]
1298
+ ANTENNA_FOCUS_LENGTH: Optional[Data[tuple[AntennaName], QuantityInMetersArray]]
990
1299
  """
991
1300
  Focus length. As defined along the optical axis of the antenna.
992
1301
  """
@@ -1002,7 +1311,7 @@ class AntennaXds:
1002
1311
  """
1003
1312
  relocatable_antennas: Optional[Attr[bool]]
1004
1313
  """ Can the antennas be moved (ALMA, VLA, NOEMA) """
1005
- type: Attr[str] = "antenna"
1314
+ type: Attr[Literal["antenna"]] = "antenna"
1006
1315
  """
1007
1316
  Type of dataset. Expected to be ``antenna``
1008
1317
  """
@@ -1029,8 +1338,6 @@ class GainCurveXds:
1029
1338
  ”SPACE-HALCA” - specific orientation model."""
1030
1339
  telescope_name: Coord[AntennaName, str]
1031
1340
  """ Useful when data is combined from mutiple arrays for example ACA + ALMA. """
1032
- # TODO: receptor_label, polarization_type, sky_dir_label set as optional
1033
- # for datasets like test_alma_ephemris_mosaic. See also BEAM_OFFSET below.
1034
1341
  receptor_label: Coord[ReceptorLabel, str]
1035
1342
  """ Names of receptors """
1036
1343
  polarization_type: Optional[Coord[tuple[AntennaName, ReceptorLabel], str]]
@@ -1045,19 +1352,23 @@ class GainCurveXds:
1045
1352
  ”VOLTAGE(EL)” - Voltage as a function of elevation;
1046
1353
  ”VOLTAGE(ZA)” - Voltage as a function of zenith angle). See https://casacore.github.io/casacore-notes/265.pdf
1047
1354
  """
1355
+ poly_term: Coord[PolyTerm, int]
1356
+ """Term orders in gain curve polynomial"""
1048
1357
 
1049
- GAIN_CURVE_SENSITIVITY: Data[tuple[AntennaName, ReceptorLabel], numpy.float32]
1050
- """ Sensitivity of the antenna expressed in K/Jy. This is what AIPS calls “DPFU”. """
1051
- GAIN_CURVE: Data[tuple[AntennaName, PolyTerm, ReceptorLabel], numpy.float32]
1358
+ GAIN_CURVE: Data[tuple[AntennaName, PolyTerm, ReceptorLabel], numpy.float64]
1052
1359
  """ Coefficients of the polynomial that describes the (power or voltage) gain. """
1053
- GAIN_CURVE_INTERVAL: Data[tuple[AntennaName], QuantityArray]
1360
+ GAIN_CURVE_INTERVAL: Data[tuple[AntennaName], QuantityInSecondsArray]
1054
1361
  """ Time interval. """
1362
+ GAIN_CURVE_SENSITIVITY: Data[
1363
+ tuple[AntennaName, ReceptorLabel], QuantityInKelvinPerJanskyArray
1364
+ ]
1365
+ """ Sensitivity of the antenna expressed in K/Jy. This is what AIPS calls “DPFU”. """
1055
1366
 
1056
1367
  measured_date: Attr[str]
1057
1368
  """
1058
1369
  Date gain curve was measured. Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)
1059
1370
  """
1060
- type: Attr[str] = "gain_curve"
1371
+ type: Attr[Literal["gain_curve"]] = "gain_curve"
1061
1372
  """
1062
1373
  Type of dataset. Expected to be ``gain_curve``
1063
1374
  """
@@ -1065,6 +1376,9 @@ class GainCurveXds:
1065
1376
 
1066
1377
  @xarray_dataset_schema
1067
1378
  class PhaseCalibrationXds:
1379
+ """
1380
+ Phase calibration dataset: signal chain phase calibration measurements.
1381
+ """
1068
1382
 
1069
1383
  # Coordinates
1070
1384
  antenna_name: Coordof[AntennaNameArray]
@@ -1081,15 +1395,13 @@ class PhaseCalibrationXds:
1081
1395
  ”SPACE-HALCA” - specific orientation model."""
1082
1396
  telescope_name: Coord[AntennaName, str]
1083
1397
  """ Useful when data is combined from mutiple arrays for example ACA + ALMA. """
1084
- # TODO: receptor_label, polarization_type, sky_dir_label set as optional
1085
- # for datasets like test_alma_ephemris_mosaic. See also BEAM_OFFSET below.
1086
- receptor_label: Optional[Coord[ReceptorLabel, str]]
1398
+ receptor_label: Coord[ReceptorLabel, str]
1087
1399
  """ Names of receptors """
1088
1400
  polarization_type: Optional[Coord[tuple[AntennaName, ReceptorLabel], str]]
1089
1401
  """ Polarization type to which each receptor responds (e.g. ”R”,”L”,”X” or ”Y”).
1090
1402
  This is the receptor polarization type as recorded in the final correlated data (e.g. ”RR”); i.e.
1091
1403
  as measured after all polarization combiners. ['X','Y'], ['R','L'] """
1092
- time: Optional[Coordof[TimeCoordArray]]
1404
+ time: Optional[Coordof[TimeInterpolatedCoordArray]]
1093
1405
  """ Time for VLBI phase cal"""
1094
1406
  time_phase_cal: Optional[Coord[TimePhaseCal, numpy.float64]]
1095
1407
  """ Time for VLBI phase cal"""
@@ -1114,7 +1426,7 @@ for each of the measured tones. See https://casacore.github.io/casacore-notes/26
1114
1426
  """
1115
1427
  PHASE_CAL_CABLE_CAL: Data[
1116
1428
  Union[tuple[AntennaName, Time], tuple[AntennaName, TimePhaseCal]],
1117
- QuantityArray,
1429
+ QuantityInSecondsArray,
1118
1430
  ]
1119
1431
  """
1120
1432
  Cable calibration measurement. This is a measurement of the delay in the cable that provides the
@@ -1123,7 +1435,7 @@ multiple receptors) so this is provided as a simple scalar. See https://casacore
1123
1435
  """
1124
1436
  PHASE_CAL_INTERVAL: Data[
1125
1437
  Union[tuple[AntennaName, Time], tuple[AntennaName, TimePhaseCal]],
1126
- QuantityArray,
1438
+ QuantityInSecondsArray,
1127
1439
  ]
1128
1440
  """
1129
1441
  Time interval. See https://casacore.github.io/casacore-notes/265.pdf
@@ -1133,13 +1445,13 @@ multiple receptors) so this is provided as a simple scalar. See https://casacore
1133
1445
  tuple[AntennaName, Time, ReceptorLabel, ToneLabel],
1134
1446
  tuple[AntennaName, TimePhaseCal, ReceptorLabel, ToneLabel],
1135
1447
  ],
1136
- QuantityArray,
1448
+ QuantityInHertzArray,
1137
1449
  ]
1138
1450
  """
1139
1451
  The sky frequencies of each measured phase-cal tone. See https://casacore.github.io/casacore-notes/265.pdf
1140
1452
  """
1141
1453
 
1142
- type: Attr[str] = "phase_calibration"
1454
+ type: Attr[Literal["phase_calibration"]] = "phase_calibration"
1143
1455
  """
1144
1456
  Type of dataset. Expected to be ``phase_calibration``
1145
1457
  """
@@ -1147,39 +1459,111 @@ multiple receptors) so this is provided as a simple scalar. See https://casacore
1147
1459
 
1148
1460
  @xarray_dataset_schema
1149
1461
  class WeatherXds:
1150
- """Weather. Contains station positions and time-dependent mean external
1151
- atmosphere and weather information"""
1462
+ """
1463
+ Weather dataset: station positions and time-dependent mean external atmosphere and weather information
1464
+ """
1152
1465
 
1153
1466
  # Coordinates
1154
1467
  station_name: Coord[StationName, str]
1155
1468
  """ Station identifier """
1156
- time: Coordof[TimeCoordArray]
1157
- """ Mid-point of the time interval """
1469
+ time: Optional[Coordof[TimeInterpolatedCoordArray]]
1470
+ """ Mid-point of the time interval. Labeled 'time' when interpolated to main time axis """
1471
+ time_weather: Optional[Coordof[TimeWeatherCoordArray]]
1472
+ """ Mid-point of the time interval. Labeled 'time_cal' when not interpolated to main time axis """
1158
1473
  antenna_name: Optional[Coordof[AntennaNameArray]]
1159
1474
  """ Antenna identifier """
1475
+ ellipsoid_pos_label: Optional[Coord[EllipsoidPosLabel, str]] = (
1476
+ "lon",
1477
+ "lat",
1478
+ "height",
1479
+ )
1480
+ """ Coordinate labels of geodetic earth location data (typically shape 3 and 'lon', 'lat', 'height')"""
1481
+ cartesian_pos_label: Optional[Coord[CartesianPosLabel, str]] = ("x", "y", "z")
1482
+ """ Coordinate labels of geocentric earth location data (typically shape 3 and 'x', 'y', 'z')"""
1160
1483
 
1161
1484
  # Data variables (all optional)
1162
- H2O: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1485
+ H2O: Optional[
1486
+ Data[
1487
+ Union[tuple[StationName, Time], tuple[StationName, TimeWeather]],
1488
+ QuantityInPerSquareMetersArray,
1489
+ ]
1490
+ ] = None
1163
1491
  """ Average column density of water """
1164
- IONOS_ELECTRON: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1492
+ IONOS_ELECTRON: Optional[
1493
+ Data[
1494
+ Union[
1495
+ tuple[StationName, Time],
1496
+ tuple[StationName, TimeWeather],
1497
+ ],
1498
+ QuantityInPerSquareMetersArray,
1499
+ ]
1500
+ ] = None
1165
1501
  """ Average column density of electrons """
1166
- PRESSURE: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1502
+ PRESSURE: Optional[
1503
+ Data[
1504
+ Union[
1505
+ tuple[StationName, Time],
1506
+ tuple[StationName, TimeWeather],
1507
+ ],
1508
+ QuantityInPascalArray,
1509
+ ]
1510
+ ] = None
1167
1511
  """ Ambient atmospheric pressure """
1168
- REL_HUMIDITY: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1512
+ REL_HUMIDITY: Optional[
1513
+ Data[
1514
+ Union[
1515
+ tuple[StationName, Time],
1516
+ tuple[StationName, TimeWeather],
1517
+ ],
1518
+ numpy.float64,
1519
+ ]
1520
+ ] = None
1169
1521
  """ Ambient relative humidity """
1170
- TEMPERATURE: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1522
+ TEMPERATURE: Optional[
1523
+ Data[
1524
+ Union[
1525
+ tuple[StationName, Time],
1526
+ tuple[StationName, TimeWeather],
1527
+ ],
1528
+ QuantityInKelvinArray,
1529
+ ]
1530
+ ] = None
1171
1531
  """ Ambient air temperature for an antenna """
1172
- DEW_POINT: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1532
+ DEW_POINT: Optional[
1533
+ Data[
1534
+ Union[
1535
+ tuple[StationName, Time],
1536
+ tuple[StationName, TimeWeather],
1537
+ ],
1538
+ QuantityInKelvinArray,
1539
+ ]
1540
+ ] = None
1173
1541
  """ Dew point """
1174
- WIND_DIRECTION: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1542
+ WIND_DIRECTION: Optional[
1543
+ Data[
1544
+ Union[
1545
+ tuple[StationName, Time],
1546
+ tuple[StationName, TimeWeather],
1547
+ ],
1548
+ QuantityInRadiansArray,
1549
+ ]
1550
+ ] = None
1175
1551
  """ Average wind direction """
1176
- WIND_SPEED: Optional[Data[tuple[StationName, Time], QuantityArray]] = None
1552
+ WIND_SPEED: Optional[
1553
+ Data[
1554
+ Union[
1555
+ tuple[StationName, Time],
1556
+ tuple[StationName, TimeWeather],
1557
+ ],
1558
+ QuantityInMetersPerSecondArray,
1559
+ ]
1560
+ ] = None
1177
1561
  """ Average wind speed """
1178
- STATION_POSITION: Optional[Data[tuple[StationName], QuantityArray]] = None
1562
+ STATION_POSITION: Optional[Data[tuple[StationName], LocationArray]] = None
1179
1563
  """ Station position """
1180
1564
 
1181
1565
  # Attributes
1182
- type: Attr[str] = "weather"
1566
+ type: Attr[Literal["weather"]] = "weather"
1183
1567
  """
1184
1568
  Type of dataset.
1185
1569
  """
@@ -1187,6 +1571,10 @@ class WeatherXds:
1187
1571
 
1188
1572
  @xarray_dataset_schema
1189
1573
  class PointingXds:
1574
+ """
1575
+ Pointing dataset: antenna pointing information.
1576
+ """
1577
+
1190
1578
  antenna_name: Coordof[AntennaNameArray]
1191
1579
  """
1192
1580
  Antenna name, as specified by baseline_antenna1/2_name in visibility dataset
@@ -1210,7 +1598,7 @@ class PointingXds:
1210
1598
  Antenna pointing direction, optionally expressed as polynomial coefficients. DIRECTION in MSv3.
1211
1599
  """
1212
1600
 
1213
- time: Optional[Coordof[TimeCoordArray]] = None
1601
+ time: Optional[Coordof[TimeInterpolatedCoordArray]] = None
1214
1602
  """
1215
1603
  Mid-point of the time interval for which the information in this row is
1216
1604
  valid. Required to use the same time measure reference as in visibility dataset.
@@ -1237,41 +1625,39 @@ class PointingXds:
1237
1625
  Data[Union[tuple[Time, AntennaName], tuple[TimePointing, AntennaName]], bool]
1238
1626
  ] = None
1239
1627
 
1240
-
1241
- @xarray_dataset_schema
1242
- class SpectralCoordXds:
1243
- # TODO
1244
- pass
1245
-
1246
-
1247
- @xarray_dataset_schema
1248
- class PhasedArrayXds:
1249
- # TODO
1250
- pass
1628
+ # Attributes
1629
+ type: Attr[Literal["pointing"]] = "pointing"
1630
+ """
1631
+ Type of dataset.
1632
+ """
1251
1633
 
1252
1634
 
1253
1635
  @xarray_dataset_schema
1254
1636
  class SystemCalibrationXds:
1255
- """System calibration. Contains time- and frequency- variable
1256
- calibration measurements for each antenna, as indexed on receptor"""
1637
+ """
1638
+ System calibration dataset: time- and frequency- variable calibration measurements for each antenna,
1639
+ as indexed on receptor
1640
+ """
1257
1641
 
1258
1642
  # Coordinates
1259
1643
  antenna_name: Coordof[AntennaNameArray]
1260
1644
  """ Antenna identifier """
1261
1645
  receptor_label: Coord[ReceptorLabel, numpy.int64]
1262
1646
  """ """
1263
- time: Optional[Coordof[TimeCoordArray]] = None
1647
+ time: Optional[Coordof[TimeInterpolatedCoordArray]] = None
1264
1648
  """ Midpoint of time for which this set of parameters is accurate. Labeled 'time' when interpolating to main time axis """
1265
1649
  time_cal: Optional[Coordof[TimeCalCoordArray]] = None
1266
1650
  """ Midpoint of time for which this set of parameters is accurate. Labeled 'time_cal' when not interpolating to main time axis """
1267
- # frequency: Optional[Coordof[FrequencyArray]] = None
1268
1651
  frequency: Optional[Coordof[FrequencyCalArray]] = None
1269
1652
  """ """
1653
+ frequency_cal: Optional[Coord[FrequencyCal, int]] = None
1654
+ """TODO: What is this?"""
1270
1655
 
1271
1656
  # Data variables (all optional)
1272
1657
  PHASE_DIFFERENCE: Optional[
1273
1658
  Data[
1274
- Union[tuple[AntennaName, TimeCal], tuple[AntennaName, Time]], numpy.float64
1659
+ Union[tuple[AntennaName, TimeCal], tuple[AntennaName, Time]],
1660
+ QuantityInRadiansArray,
1275
1661
  ]
1276
1662
  ] = None
1277
1663
  """ Phase difference between receptor 0 and receptor 1 """
@@ -1285,7 +1671,7 @@ class SystemCalibrationXds:
1285
1671
  tuple[AntennaName, Time, ReceptorLabel, Frequency],
1286
1672
  tuple[AntennaName, Time, ReceptorLabel],
1287
1673
  ],
1288
- QuantityArray,
1674
+ QuantityInKelvinArray,
1289
1675
  ]
1290
1676
  ] = None
1291
1677
  """ Calibration temp """
@@ -1299,7 +1685,7 @@ class SystemCalibrationXds:
1299
1685
  tuple[AntennaName, Time, ReceptorLabel, Frequency],
1300
1686
  tuple[AntennaName, Time, ReceptorLabel],
1301
1687
  ],
1302
- QuantityArray,
1688
+ QuantityInKelvinArray,
1303
1689
  ]
1304
1690
  ] = None
1305
1691
  """ Receiver temperature """
@@ -1313,7 +1699,7 @@ class SystemCalibrationXds:
1313
1699
  tuple[AntennaName, Time, ReceptorLabel, Frequency],
1314
1700
  tuple[AntennaName, Time, ReceptorLabel],
1315
1701
  ],
1316
- QuantityArray,
1702
+ QuantityInKelvinArray,
1317
1703
  ]
1318
1704
  ] = None
1319
1705
  """ Sky temperature """
@@ -1327,7 +1713,7 @@ class SystemCalibrationXds:
1327
1713
  tuple[AntennaName, Time, ReceptorLabel, Frequency],
1328
1714
  tuple[AntennaName, Time, ReceptorLabel],
1329
1715
  ],
1330
- QuantityArray,
1716
+ QuantityInKelvinArray,
1331
1717
  ]
1332
1718
  ] = None
1333
1719
  """ System temperature """
@@ -1341,7 +1727,7 @@ class SystemCalibrationXds:
1341
1727
  tuple[AntennaName, Time, ReceptorLabel, Frequency],
1342
1728
  tuple[AntennaName, Time, ReceptorLabel],
1343
1729
  ],
1344
- QuantityArray,
1730
+ QuantityInKelvinArray,
1345
1731
  ]
1346
1732
  ] = None
1347
1733
  """ Antenna temperature """
@@ -1355,21 +1741,35 @@ class SystemCalibrationXds:
1355
1741
  tuple[AntennaName, Time, ReceptorLabel, Frequency],
1356
1742
  tuple[AntennaName, Time, ReceptorLabel],
1357
1743
  ],
1358
- QuantityArray,
1744
+ QuantityInKelvinArray,
1359
1745
  ]
1360
1746
  ] = None
1361
1747
  """ TANT/TSYS """
1362
1748
 
1363
1749
  # Attributes
1364
- type: Attr[str] = "system_calibration"
1750
+ type: Attr[Literal["system_calibration"]] = "system_calibration"
1365
1751
  """
1366
1752
  Type of dataset.
1367
1753
  """
1368
1754
 
1369
1755
 
1756
+ @xarray_dataset_schema
1757
+ class PhasedArrayXds:
1758
+ """Not specified. Not implemented."""
1759
+
1760
+ pass
1761
+
1762
+
1763
+ @xarray_dataset_schema
1764
+ class DopplerXds:
1765
+ """Not specified. Not implemented."""
1766
+
1767
+ pass
1768
+
1769
+
1370
1770
  @xarray_dataset_schema
1371
1771
  class VisibilityXds:
1372
- """TODO: documentation"""
1772
+ """Main dataset for interferometric data"""
1373
1773
 
1374
1774
  # --- Required Coordinates ---
1375
1775
  time: Coordof[TimeCoordArray]
@@ -1377,27 +1777,23 @@ class VisibilityXds:
1377
1777
  The time coordinate is the mid-point of the nominal sampling interval, as
1378
1778
  specified in the ``ms_v4.time.attrs['integration_time']`` (ms v2 interval).
1379
1779
  """
1380
- baseline_id: Optional[Coordof[BaselineArray]] # IF. not present in main_sd_xds
1780
+ baseline_id: Coordof[BaselineArray]
1381
1781
  """ Baseline ID """
1382
- antenna_name: Optional[
1383
- Coordof[AntennaNameArray]
1384
- ] # Single-dish. not present in main_xds
1385
- """ antenna_name """
1386
1782
  frequency: Coordof[FrequencyArray]
1387
1783
  """Center frequencies for each channel."""
1388
1784
  polarization: Coordof[PolarizationArray]
1389
1785
  """
1390
1786
  Labels for polarization types, e.g. ``['XX','XY','YX','YY']``, ``['RR','RL','LR','LL']``.
1391
1787
  """
1392
- polarization_mixed: Optional[Coord[tuple[BaselineId, Polarization], str]]
1393
- """
1394
- If the polarizations are not constant over baseline
1395
- """
1396
- uvw_label: Optional[Coordof[UvwLabelArray]]
1397
- """ u,v,w """
1398
- baseline_antenna1_name: Optional[Coordof[BaselineAntennaNameArray]] # IF
1788
+
1789
+ # --- Required data variables ---
1790
+
1791
+ VISIBILITY: Dataof[VisibilityArray]
1792
+ """Complex visibilities, either simulated or measured by interferometer."""
1793
+
1794
+ baseline_antenna1_name: Coordof[BaselineAntennaNameArray]
1399
1795
  """Antenna name for 1st antenna in baseline. Maps to ``attrs['antenna_xds'].antenna_name``"""
1400
- baseline_antenna2_name: Optional[Coordof[BaselineAntennaNameArray]] # IF
1796
+ baseline_antenna2_name: Coordof[BaselineAntennaNameArray]
1401
1797
  """Antenna name for 2nd antenna in baseline. Maps to ``attrs['antenna_xds'].antenna_name``"""
1402
1798
 
1403
1799
  # --- Required Attributes ---
@@ -1406,43 +1802,42 @@ class VisibilityXds:
1406
1802
  processor_info: Attr[ProcessorInfoDict]
1407
1803
  antenna_xds: Attr[AntennaXds]
1408
1804
 
1409
- schema_version: Attr[str] = None
1805
+ schema_version: Attr[str]
1410
1806
  """Semantic version of xradio data format"""
1411
- creation_date: Attr[str] = None
1807
+ creation_date: Attr[str]
1412
1808
  """Date visibility dataset was created . Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
1413
1809
 
1810
+ type: Attr[Literal["visibility"]] = "visibility"
1811
+ """
1812
+ Dataset type
1813
+ """
1814
+
1414
1815
  # --- Optional Coordinates ---
1816
+ polarization_mixed: Optional[Coord[tuple[BaselineId, Polarization], str]] = None
1817
+ """
1818
+ If the polarizations are not constant over baseline
1819
+ """
1820
+ uvw_label: Optional[Coordof[UvwLabelArray]] = None
1821
+ """ u,v,w """
1415
1822
  scan_number: Optional[Coord[Time, Union[numpy.int64, numpy.int32]]] = None
1416
1823
  """Arbitary scan number to identify data taken in the same logical scan."""
1417
1824
 
1418
- # --- Required data variables ---
1419
-
1420
1825
  # --- Optional data variables / arrays ---
1421
1826
 
1422
- # Either VISIBILITY (interferometry) or SPECTRUM (single-dish)
1423
- VISIBILITY: Optional[Dataof[VisibilityArray]] = None
1424
- """Complex visibilities, either simulated or measured by interferometer."""
1425
- SPECTRUM: Optional[Dataof[SpectrumArray]] = None
1426
- """Single dish data, either simulated or measured by an antenna."""
1427
-
1428
- VISIBILITY_CORRECTED: Optional[Dataof[VisibilityArray]] = None
1429
- VISIBILITY_MODEL: Optional[Dataof[VisibilityArray]] = None
1430
- SPECTRUM_CORRECTED: Optional[Dataof[SpectrumArray]] = None
1827
+ # VISIBILITY_CORRECTED: Optional[Dataof[VisibilityArray]] = None
1828
+ # VISIBILITY_MODEL: Optional[Dataof[VisibilityArray]] = None
1431
1829
 
1432
- FLAG: Optional[Dataof[FlagArray]] = None
1433
- WEIGHT: Optional[Dataof[WeightArray]] = None
1434
- UVW: Optional[Dataof[UvwArray]] = None
1830
+ FLAG: Dataof[FlagArray] = None
1831
+ WEIGHT: Dataof[WeightArray] = None
1832
+ UVW: Dataof[UvwArray] = None
1435
1833
  EFFECTIVE_INTEGRATION_TIME: Optional[
1436
1834
  Data[
1437
1835
  Union[
1438
1836
  tuple[Time, BaselineId],
1439
1837
  tuple[Time, BaselineId, Frequency],
1440
1838
  tuple[Time, BaselineId, Frequency, Polarization],
1441
- tuple[Time, AntennaName], # SD
1442
- tuple[Time, AntennaName, Frequency], # SD
1443
- tuple[Time, AntennaName, Frequency, Polarization], # SD
1444
1839
  ],
1445
- QuantityArray,
1840
+ QuantityInSecondsArray,
1446
1841
  ]
1447
1842
  ] = None
1448
1843
  """
@@ -1482,7 +1877,103 @@ class VisibilityXds:
1482
1877
  The id assigned to this combination of spectral window and polarization setup.
1483
1878
  """
1484
1879
 
1485
- type: Attr[str] = "visibility"
1880
+
1881
+ @xarray_dataset_schema
1882
+ class SpectrumXds:
1883
+ """Main dataset for single dish data"""
1884
+
1885
+ # --- Required Coordinates ---
1886
+ time: Coordof[TimeCoordArray]
1887
+ """
1888
+ The time coordinate is the mid-point of the nominal sampling interval, as
1889
+ specified in the ``ms_v4.time.attrs['integration_time']`` (ms v2 interval).
1890
+ """
1891
+ antenna_name: Coordof[AntennaNameArray]
1892
+ """ antenna_name """
1893
+ frequency: Coordof[FrequencyArray]
1894
+ """Center frequencies for each channel."""
1895
+ polarization: Coordof[PolarizationArray]
1896
+ """
1897
+ Labels for polarization types, e.g. ``['XX','XY','YX','YY']``, ``['RR','RL','LR','LL']``.
1898
+ """
1899
+
1900
+ # --- Required data variables ---
1901
+ SPECTRUM: Dataof[SpectrumArray]
1902
+ """Single dish data, either simulated or measured by an antenna."""
1903
+
1904
+ # --- Required Attributes ---
1905
+ partition_info: Attr[PartitionInfoDict]
1906
+ observation_info: Attr[ObservationInfoDict]
1907
+ processor_info: Attr[ProcessorInfoDict]
1908
+ antenna_xds: Attr[AntennaXds]
1909
+
1910
+ schema_version: Attr[str]
1911
+ """Semantic version of xradio data format"""
1912
+ creation_date: Attr[str]
1913
+ """Date MSv4 was created . Format: YYYY-MM-DDTHH:mm:ss.SSS (ISO 8601)"""
1914
+
1915
+ type: Attr[Literal["spectrum"]] = "spectrum"
1486
1916
  """
1487
1917
  Dataset type
1488
1918
  """
1919
+
1920
+ # --- Optional Coordinates ---
1921
+ polarization_mixed: Optional[Coord[tuple[AntennaName, Polarization], str]] = None
1922
+ """
1923
+ If the polarizations are not constant over baseline
1924
+ """
1925
+ scan_number: Optional[Coord[Time, Union[numpy.int64, numpy.int32]]] = None
1926
+ """Arbitary scan number to identify data taken in the same logical scan."""
1927
+
1928
+ # SPECTRUM_CORRECTED: Optional[Dataof[SpectrumArray]] = None
1929
+
1930
+ FLAG: Dataof[FlagArray] = None
1931
+ WEIGHT: Dataof[WeightArray] = None
1932
+
1933
+ # --- Optional data variables / arrays ---
1934
+ EFFECTIVE_INTEGRATION_TIME: Optional[
1935
+ Data[
1936
+ Union[
1937
+ tuple[Time, AntennaName],
1938
+ tuple[Time, AntennaName, Frequency],
1939
+ tuple[Time, AntennaName, Frequency, Polarization],
1940
+ ],
1941
+ QuantityInSecondsArray,
1942
+ ]
1943
+ ] = None
1944
+ """
1945
+ The integration time, including the effects of missing data, in contrast to
1946
+ ``integration_time`` attribute of the ``time`` coordinate,
1947
+ see :py:class:`TimeArray`. (MS v2: ``exposure``).
1948
+ """
1949
+ TIME_CENTROID: Optional[Dataof[TimeSamplingArray]] = None
1950
+ """
1951
+ The time centroid of the visibility, includes the effects of missing data
1952
+ unlike the ``time`` coordinate, see :py:class:`TimeArray`.
1953
+ """
1954
+ TIME_CENTROID_EXTRA_PRECISION: Optional[Dataof[TimeSamplingArray]] = None
1955
+ """Additional precision for ``TIME_CENTROID``"""
1956
+ EFFECTIVE_CHANNEL_WIDTH: Optional[Dataof[FreqSamplingArray]] = None
1957
+ """The channel bandwidth that includes the effects of missing data."""
1958
+ FREQUENCY_CENTROID: Optional[Dataof[FreqSamplingArray]] = None
1959
+ """Includes the effects of missing data unlike ``frequency``."""
1960
+
1961
+ # --- Optional Attributes ---
1962
+ pointing_xds: Optional[Attr[PointingXds]] = None
1963
+ system_calibration_xds: Optional[Attr[SystemCalibrationXds]] = None
1964
+ gain_curve_xds: Optional[Attr[GainCurveXds]] = None
1965
+ phase_calibration_xds: Optional[Attr[PhaseCalibrationXds]] = None
1966
+ weather_xds: Optional[Attr[WeatherXds]] = None
1967
+ phased_array_xds: Optional[Attr[PhasedArrayXds]] = None
1968
+
1969
+ xradio_version: Optional[Attr[str]] = None
1970
+ """ Version of XRADIO used if converted from MSv2. """
1971
+
1972
+ intent: Optional[Attr[str]] = None
1973
+ """Identifies the intention of the scan, such as to calibrate or observe a
1974
+ target. See :ref:`scan intents` for possible values.
1975
+ """
1976
+ data_description_id: Optional[Attr[str]] = None
1977
+ """
1978
+ The id assigned to this combination of spectral window and polarization setup.
1979
+ """