xradio 0.0.56__py3-none-any.whl → 0.0.59__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 (63) hide show
  1. xradio/__init__.py +2 -2
  2. xradio/_utils/_casacore/casacore_from_casatools.py +12 -2
  3. xradio/_utils/_casacore/tables.py +1 -0
  4. xradio/_utils/coord_math.py +22 -23
  5. xradio/_utils/dict_helpers.py +76 -11
  6. xradio/_utils/schema.py +5 -2
  7. xradio/_utils/zarr/common.py +1 -73
  8. xradio/image/_util/_casacore/xds_from_casacore.py +49 -33
  9. xradio/image/_util/_casacore/xds_to_casacore.py +41 -14
  10. xradio/image/_util/_fits/xds_from_fits.py +146 -35
  11. xradio/image/_util/casacore.py +4 -3
  12. xradio/image/_util/common.py +4 -4
  13. xradio/image/_util/image_factory.py +8 -8
  14. xradio/image/image.py +45 -5
  15. xradio/measurement_set/__init__.py +19 -9
  16. xradio/measurement_set/_utils/__init__.py +1 -3
  17. xradio/measurement_set/_utils/_msv2/__init__.py +0 -0
  18. xradio/measurement_set/_utils/_msv2/_tables/read.py +17 -76
  19. xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py +2 -685
  20. xradio/measurement_set/_utils/_msv2/conversion.py +174 -156
  21. xradio/measurement_set/_utils/_msv2/create_antenna_xds.py +9 -16
  22. xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py +128 -222
  23. xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py +1 -2
  24. xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +8 -7
  25. xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +31 -74
  26. xradio/measurement_set/_utils/_msv2/partition_queries.py +1 -261
  27. xradio/measurement_set/_utils/_msv2/subtables.py +0 -107
  28. xradio/measurement_set/_utils/_utils/interpolate.py +60 -0
  29. xradio/measurement_set/_utils/_zarr/encoding.py +2 -7
  30. xradio/measurement_set/convert_msv2_to_processing_set.py +0 -2
  31. xradio/measurement_set/load_processing_set.py +2 -2
  32. xradio/measurement_set/measurement_set_xdt.py +20 -16
  33. xradio/measurement_set/open_processing_set.py +1 -3
  34. xradio/measurement_set/processing_set_xdt.py +54 -841
  35. xradio/measurement_set/schema.py +122 -132
  36. xradio/schema/check.py +95 -101
  37. xradio/schema/dataclass.py +159 -22
  38. xradio/schema/export.py +99 -0
  39. xradio/schema/metamodel.py +51 -16
  40. xradio/schema/typing.py +5 -5
  41. xradio/sphinx/schema_table.py +41 -77
  42. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/METADATA +20 -5
  43. xradio-0.0.59.dist-info/RECORD +65 -0
  44. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/WHEEL +1 -1
  45. xradio/image/_util/fits.py +0 -13
  46. xradio/measurement_set/_utils/_msv2/_tables/load.py +0 -66
  47. xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py +0 -490
  48. xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py +0 -398
  49. xradio/measurement_set/_utils/_msv2/_tables/write.py +0 -323
  50. xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py +0 -388
  51. xradio/measurement_set/_utils/_msv2/chunks.py +0 -115
  52. xradio/measurement_set/_utils/_msv2/descr.py +0 -165
  53. xradio/measurement_set/_utils/_msv2/msv2_msv3.py +0 -7
  54. xradio/measurement_set/_utils/_msv2/partitions.py +0 -392
  55. xradio/measurement_set/_utils/_utils/cds.py +0 -40
  56. xradio/measurement_set/_utils/_utils/xds_helper.py +0 -404
  57. xradio/measurement_set/_utils/_zarr/read.py +0 -263
  58. xradio/measurement_set/_utils/_zarr/write.py +0 -329
  59. xradio/measurement_set/_utils/msv2.py +0 -106
  60. xradio/measurement_set/_utils/zarr.py +0 -133
  61. xradio-0.0.56.dist-info/RECORD +0 -78
  62. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/licenses/LICENSE.txt +0 -0
  63. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/top_level.txt +0 -0
@@ -18,10 +18,9 @@ from xradio.measurement_set._utils._msv2._tables.read import (
18
18
  load_generic_table,
19
19
  )
20
20
  from xradio._utils.list_and_array import cast_to_str, get_pad_value
21
-
21
+ from xradio._utils.dict_helpers import make_quantity_attrs
22
22
  from xradio._utils.coord_math import (
23
23
  convert_to_si_units,
24
- add_position_offsets,
25
24
  wrap_to_pi,
26
25
  )
27
26
 
@@ -45,7 +44,7 @@ def create_field_and_source_xds(
45
44
  is_single_dish: bool,
46
45
  time_min_max: Tuple[np.float64, np.float64],
47
46
  ephemeris_interpolate: bool = True,
48
- ) -> tuple[xr.Dataset, int]:
47
+ ) -> tuple[xr.Dataset, np.ndarray, int]:
49
48
  """
50
49
  Create a field and source xarray dataset (xds) from the given input file, field ID, and spectral window ID.
51
50
  Data is extracted from the FIELD and SOURCE tables and if there is ephemeris data, it is also extracted.
@@ -72,6 +71,8 @@ def create_field_and_source_xds(
72
71
  -------
73
72
  field_and_source_xds : xr.Dataset
74
73
  The xarray dataset containing the field and source information.
74
+ source_id : np.ndarray[int]
75
+ Source ID(s) corresponding to the field(s)
75
76
  num_lines : int
76
77
  Sum of num_lines for all unique sources.
77
78
  """
@@ -158,6 +159,10 @@ def extract_ephemeris_info(
158
159
  # Consequently a lot of hardcoding is needed to extract the information.
159
160
  # https://casadocs.readthedocs.io/en/latest/notebooks/external-data.html
160
161
 
162
+ xds = xds.assign_coords(
163
+ {"sky_dis_label": ["dist"], "cartesian_pos_label": ["x", "y", "z"]}
164
+ )
165
+
161
166
  # Only read data between the min and max times of the visibility data in the MSv4.
162
167
  min_max_mjd = (
163
168
  convert_casacore_time_to_mjd(time_min_max[0]),
@@ -214,44 +219,64 @@ def extract_ephemeris_info(
214
219
  temp_xds = xr.Dataset()
215
220
 
216
221
  # Add mandatory data: OBSERVER_POSITION
217
- observer_position = [
218
- ephemeris_meta["GeoLong"],
219
- ephemeris_meta["GeoLat"],
220
- ephemeris_meta["GeoDist"],
221
- ]
222
+ # Convert Observer position to geodetic coordinates
223
+ from astropy import units as u
224
+ from astropy.coordinates import EarthLocation
225
+ from astropy.time import Time
226
+
227
+ # Create an EarthLocation object for the geodetic coordinates
228
+ # Assume that geodetic coordinates are given in degrees and meters
229
+ location = EarthLocation.from_geodetic(
230
+ lon=ephemeris_meta["GeoLong"] * u.deg,
231
+ lat=ephemeris_meta["GeoLat"] * u.deg,
232
+ height=ephemeris_meta["GeoDist"] * u.m,
233
+ ellipsoid="WGS84", # Explicitly specify WGS84
234
+ )
235
+
236
+ # Get the ITRS Cartesian coordinates (x, y, z)
237
+ observer_position = location.itrs.cartesian.xyz
238
+
222
239
  temp_xds["OBSERVER_POSITION"] = xr.DataArray(
223
- observer_position, dims=["ellipsoid_pos_label"]
240
+ observer_position, dims=["cartesian_pos_label"]
224
241
  )
225
242
  temp_xds["OBSERVER_POSITION"].attrs.update(
226
243
  {
227
244
  "type": "location",
228
- "units": ["deg", "deg", "m"],
229
- "data": observer_position,
245
+ "units": "m",
230
246
  "frame": "ITRS",
231
247
  "origin_object_name": "Earth",
232
248
  "coordinate_system": ephemeris_meta["obsloc"].lower(),
233
- "ellipsoid": "WGS84",
234
249
  }
235
- ) # I think the units are ['deg','deg','m'] and 'WGS84'.
250
+ )
236
251
 
237
- # Add (optional) data: SOURCE_LOCATION (POSITION / sky_pos_label)
238
- temp_xds["SOURCE_LOCATION"] = xr.DataArray(
252
+ temp_xds["SOURCE_DIRECTION"] = xr.DataArray(
239
253
  np.column_stack(
240
254
  (
241
255
  ephemeris_xds["RA"].data,
242
256
  ephemeris_xds["DEC"].data,
243
- ephemeris_xds["Rho"].data,
244
257
  )
245
258
  ),
246
- dims=["time_ephemeris", "sky_pos_label"],
259
+ dims=["time_ephemeris", "sky_dir_label"],
247
260
  )
261
+
262
+ temp_xds["SOURCE_DISTANCE"] = xr.DataArray(
263
+ np.column_stack((ephemeris_xds["Rho"].data,)),
264
+ dims=["time_ephemeris", "sky_dis_label"],
265
+ )
266
+
248
267
  # Have to use cast_to_str because the ephemeris table units are not consistently in a list or a string.
249
- sky_coord_units = [
250
- cast_to_str(ephemeris_column_description["RA"]["keywords"][unit_keyword]),
251
- cast_to_str(ephemeris_column_description["DEC"]["keywords"][unit_keyword]),
252
- cast_to_str(ephemeris_column_description["Rho"]["keywords"][unit_keyword]),
253
- ]
254
- temp_xds["SOURCE_LOCATION"].attrs.update(
268
+ sky_coord_units = cast_to_str(
269
+ ephemeris_column_description["RA"]["keywords"][unit_keyword]
270
+ )
271
+
272
+ temp_xds["SOURCE_DIRECTION"].attrs.update(
273
+ {"type": "sky_coord", "frame": sky_coord_frame, "units": sky_coord_units}
274
+ )
275
+
276
+ sky_coord_units = cast_to_str(
277
+ ephemeris_column_description["Rho"]["keywords"][unit_keyword]
278
+ )
279
+ temp_xds["SOURCE_DISTANCE"].attrs.update(
255
280
  {"type": "sky_coord", "frame": sky_coord_frame, "units": sky_coord_units}
256
281
  )
257
282
 
@@ -281,16 +306,13 @@ def extract_ephemeris_info(
281
306
  msv4_var_name = msv4_variable_def[0]
282
307
  if msv4_var_name in temp_xds:
283
308
  temp_xds[msv4_var_name].attrs.update(
284
- {
285
- "type": "quantity",
286
- "units": [
287
- cast_to_str(
288
- ephemeris_column_description[generic_var_name]["keywords"][
289
- unit_keyword
290
- ]
291
- )
292
- ],
293
- }
309
+ make_quantity_attrs(
310
+ cast_to_str(
311
+ ephemeris_column_description[generic_var_name]["keywords"][
312
+ unit_keyword
313
+ ]
314
+ )
315
+ )
294
316
  )
295
317
 
296
318
  # Add optional data: SUB_OBSERVER_DIRECTION and SUB_SOLAR_POSITION
@@ -307,10 +329,9 @@ def extract_ephemeris_info(
307
329
  (
308
330
  ephemeris_xds[key_lon].data,
309
331
  ephemeris_xds[key_lat].data,
310
- np.zeros(ephemeris_xds[key_lon].shape),
311
332
  )
312
333
  ),
313
- dims=["time_ephemeris", "ellipsoid_pos_label"],
334
+ dims=["time_ephemeris", "ellipsoid_dir_label"],
314
335
  )
315
336
 
316
337
  temp_xds["SUB_OBSERVER_DIRECTION"].attrs.update(
@@ -319,54 +340,55 @@ def extract_ephemeris_info(
319
340
  "frame": "Undefined",
320
341
  "origin_object_name": ephemeris_meta["NAME"],
321
342
  "coordinate_system": "planetodetic",
322
- "units": [
323
- cast_to_str(
324
- ephemeris_column_description[key_lon]["keywords"][unit_keyword]
325
- ),
326
- cast_to_str(
327
- ephemeris_column_description[key_lat]["keywords"][unit_keyword]
328
- ),
329
- "m",
330
- ],
343
+ "units": cast_to_str(
344
+ ephemeris_column_description[key_lon]["keywords"][unit_keyword]
345
+ ),
331
346
  }
332
347
  )
333
348
 
334
349
  if "SI_lon" in ephemeris_xds.data_vars:
335
- temp_xds["SUB_SOLAR_POSITION"] = xr.DataArray(
350
+ temp_xds["SUB_SOLAR_DIRECTION"] = xr.DataArray(
336
351
  np.column_stack(
337
352
  (
338
353
  ephemeris_xds["SI_lon"].data,
339
354
  ephemeris_xds["SI_lat"].data,
340
- ephemeris_xds["r"].data,
341
355
  )
342
356
  ),
343
- dims=["time_ephemeris", "ellipsoid_pos_label"],
357
+ dims=["time_ephemeris", "ellipsoid_dir_label"],
344
358
  )
345
- temp_xds["SUB_SOLAR_POSITION"].attrs.update(
359
+ temp_xds["SUB_SOLAR_DIRECTION"].attrs.update(
346
360
  {
347
361
  "type": "location",
348
362
  "frame": "Undefined",
349
363
  "origin_object_name": "Sun",
350
364
  "coordinate_system": "planetodetic",
351
- "units": [
352
- cast_to_str(
353
- ephemeris_column_description["SI_lon"]["keywords"][unit_keyword]
354
- ),
355
- cast_to_str(
356
- ephemeris_column_description["SI_lat"]["keywords"][unit_keyword]
357
- ),
358
- cast_to_str(
359
- ephemeris_column_description["r"]["keywords"][unit_keyword]
360
- ),
361
- ],
365
+ "units": cast_to_str(
366
+ ephemeris_column_description["SI_lon"]["keywords"][unit_keyword]
367
+ ),
368
+ }
369
+ )
370
+
371
+ temp_xds["SUB_SOLAR_DISTANCE"] = xr.DataArray(
372
+ [ephemeris_xds["r"].data],
373
+ dims=["time_ephemeris", "ellipsoid_dis_label"],
374
+ )
375
+ temp_xds["SUB_SOLAR_DISTANCE"].attrs.update(
376
+ {
377
+ "type": "location",
378
+ "frame": "Undefined",
379
+ "origin_object_name": "Sun",
380
+ "coordinate_system": "planetodetic",
381
+ "units": cast_to_str(
382
+ ephemeris_column_description["r"]["keywords"][unit_keyword]
383
+ ),
362
384
  }
363
385
  )
364
386
 
365
387
  # We are using the "time_ephemeris" label because it might not match the optional time axis of the source and field info. If ephemeris_interpolate=True then rename it to time.
366
388
  coords = {
367
- "ellipsoid_pos_label": ["lon", "lat", "dist"],
389
+ "ellipsoid_dir_label": ["lon", "lat"],
390
+ "ellipsoid_dis_label": ["dist"],
368
391
  "time_ephemeris": ephemeris_xds["time"].data,
369
- "sky_pos_label": ["ra", "dec", "dist"],
370
392
  }
371
393
  temp_xds = temp_xds.assign_coords(coords)
372
394
  temp_xds["time_ephemeris"].attrs.update(standard_time_coord_attrs)
@@ -379,10 +401,18 @@ def extract_ephemeris_info(
379
401
  temp_xds = rename_and_interpolate_to_time(
380
402
  temp_xds, "time_ephemeris", interp_time, "field_and_source_xds"
381
403
  )
382
- source_location_interp = temp_xds["SOURCE_LOCATION"]
404
+ source_direction_interp = temp_xds["SOURCE_DIRECTION"]
405
+ source_distance_interp = temp_xds["SOURCE_DISTANCE"]
406
+
383
407
  else:
384
- source_location_interp = interpolate_to_time(
385
- temp_xds["SOURCE_LOCATION"],
408
+ source_direction_interp = interpolate_to_time(
409
+ temp_xds["SOURCE_DIRECTION"],
410
+ interp_time,
411
+ "field_and_source_xds",
412
+ "time_ephemeris",
413
+ )
414
+ source_distance_interp = interpolate_to_time(
415
+ temp_xds["SOURCE_DISTANCE"],
386
416
  interp_time,
387
417
  "field_and_source_xds",
388
418
  "time_ephemeris",
@@ -390,68 +420,38 @@ def extract_ephemeris_info(
390
420
 
391
421
  xds = xr.merge([xds, temp_xds])
392
422
 
393
- # Add the SOURCE_LOCATION to the FIELD_PHASE_CENTER or FIELD_REFERENCE_CENTER. Ephemeris obs: When loaded from the MSv2 field table the FIELD_REFERENCE_CENTER or FIELD_PHASE_CENTER only contain an offset from the SOURCE_LOCATION.
394
- # We also need to add a distance dimension to the FIELD_PHASE_CENTER or FIELD_REFERENCE_CENTER to match the SOURCE_LOCATION.
395
- # FIELD_PHASE_CENTER is used for interferometer data and FIELD_REFERENCE_CENTER is used for single dish data.
423
+ # Add the SOURCE_DIRECTION to the FIELD_PHASE_CENTER or FIELD_REFERENCE_CENTER. Ephemeris obs: When loaded from the MSv2 field table the FIELD_REFERENCE_CENTER or FIELD_PHASE_CENTER only contain an offset from the SOURCE_DIRECTION.
424
+ # We also need to add a distance dimension to the FIELD_PHASE_CENTER or FIELD_REFERENCE_CENTER to match the SOURCE_DIRECTION.
425
+ # FIELD_PHASE_CENTER_DIRECTION is used for interferometer data and FIELD_REFERENCE_CENTER_DIRECTION is used for single dish data.
396
426
  if is_single_dish:
397
- center_dv = "FIELD_REFERENCE_CENTER"
427
+ center_dir_dv = "FIELD_REFERENCE_CENTER_DIRECTION"
428
+ center_dis_dv = "FIELD_REFERENCE_CENTER_DISTANCE"
398
429
  else:
399
- center_dv = "FIELD_PHASE_CENTER"
430
+ center_dir_dv = "FIELD_PHASE_CENTER_DIRECTION"
431
+ center_dis_dv = "FIELD_PHASE_CENTER_DISTANCE"
400
432
 
401
433
  xds = xds.sel(field_name=field_names) # Expand for all times in ms
402
434
  xds = xds.assign_coords({"time": ("field_name", interp_time)})
403
435
  xds["time"].attrs.update(standard_time_coord_attrs)
404
436
  xds = xds.swap_dims({"field_name": "time"})
405
437
 
406
- source_location_interp
407
- field_phase_center = wrap_to_pi(
408
- xds[center_dv].values + source_location_interp[:, 0:2].values
438
+ field_phase_center_direction = wrap_to_pi(
439
+ xds[center_dir_dv].values + source_direction_interp.values
409
440
  )
410
441
 
411
- field_phase_center = np.column_stack(
412
- (field_phase_center, np.zeros(xds[center_dv].values.shape[0]))
442
+ xds[center_dir_dv] = xr.DataArray(
443
+ field_phase_center_direction,
444
+ dims=["time", "sky_dir_label"],
413
445
  )
414
446
 
415
- field_phase_center[:, -1] = (
416
- field_phase_center[:, -1] + source_location_interp[:, -1].values
447
+ xds[center_dis_dv] = xr.DataArray(
448
+ source_distance_interp.values,
449
+ dims=["time", "sky_dis_label"],
417
450
  )
418
451
 
419
- xds[center_dv] = xr.DataArray(
420
- field_phase_center,
421
- dims=["time", "sky_pos_label"],
422
- )
452
+ xds[center_dir_dv].attrs.update(xds["SOURCE_DIRECTION"].attrs)
423
453
 
424
- # if "time" in xds[center_dv].coords:
425
- # assert (
426
- # interp_time is not None
427
- # ), 'ephemeris_interpolate must be True if there is ephemeris data and multiple fields (this will occur if "FIELD_ID" is not in partition_scheme).'
428
-
429
- # field_phase_center = wrap_to_pi(
430
- # xds[center_dv].values + xds["SOURCE_LOCATION"][:, 0:2].values
431
- # )
432
- # field_phase_center = np.column_stack(
433
- # (field_phase_center, np.zeros(xds[center_dv].values.shape[0]))
434
- # )
435
- # field_phase_center[:, -1] = (
436
- # field_phase_center[:, -1] + xds["SOURCE_LOCATION"][:, -1].values
437
- # )
438
-
439
- # xds[center_dv] = xr.DataArray(
440
- # field_phase_center,
441
- # dims=[xds["SOURCE_LOCATION"].dims[0], "sky_pos_label"],
442
- # )
443
- # else:
444
- # field_phase_center = (
445
- # np.append(xds[center_dv].values, 0) + xds["SOURCE_LOCATION"].values
446
- # )
447
- # field_phase_center[:, 0:2] = wrap_to_pi(field_phase_center[:, 0:2])
448
-
449
- # xds[center_dv] = xr.DataArray(
450
- # field_phase_center,
451
- # dims=[xds["SOURCE_LOCATION"].dims[0], "sky_pos_label"],
452
- # )
453
-
454
- xds[center_dv].attrs.update(xds["SOURCE_LOCATION"].attrs)
454
+ xds[center_dis_dv].attrs.update(xds["SOURCE_DISTANCE"].attrs)
455
455
 
456
456
  return xds
457
457
 
@@ -573,7 +573,9 @@ def pad_missing_sources(
573
573
  for missing_id in missing_source_ids:
574
574
  missing_source_xds[concat_dim] = missing_id
575
575
  xdss_to_concat.append(missing_source_xds)
576
- filled_source_xds = xr.concat(xdss_to_concat, concat_dim).sortby(concat_dim)
576
+ filled_source_xds = xr.concat(xdss_to_concat, concat_dim, join="outer").sortby(
577
+ concat_dim
578
+ )
577
579
 
578
580
  return filled_source_xds
579
581
 
@@ -611,7 +613,7 @@ def extract_source_info(
611
613
 
612
614
  if all(source_id == -1):
613
615
  logger.warning(
614
- f"Source_id is -1. No source information will be included in the field_and_source_xds."
616
+ "Source_id is -1. No source information will be included in the field_and_source_xds."
615
617
  )
616
618
  xds = xds.assign_coords(
617
619
  {"source_name": ("field_name", unknown)}
@@ -655,7 +657,7 @@ def extract_source_info(
655
657
  # ), "Can only process source table with a single time entry for a source_id and spectral_window_id."
656
658
  if len(source_xds.TIME) > len(unique_source_id):
657
659
  logger.warning(
658
- f"Source table has more than one time entry for a source_id and spectral_window_id. This is not currently supported. Only the first time entry will be used."
660
+ "Source table has more than one time entry for a source_id and spectral_window_id. This is not currently supported. Only the first time entry will be used."
659
661
  )
660
662
  source_xds = source_xds.drop_duplicates("SOURCE_ID", keep="first")
661
663
 
@@ -689,9 +691,6 @@ def extract_source_info(
689
691
  # If ephemeris data is present we ignore the SOURCE_DIRECTION in the source table.
690
692
  if not is_ephemeris:
691
693
  direction_msv2_col = "DIRECTION"
692
- msv4_measure = column_description_casacore_to_msv4_measure(
693
- source_column_description[direction_msv2_col]
694
- )
695
694
 
696
695
  msv2_direction_dims = source_xds[direction_msv2_col].dims
697
696
  if (
@@ -709,7 +708,7 @@ def extract_source_info(
709
708
  location_msv4_measure = column_description_casacore_to_msv4_measure(
710
709
  source_column_description[direction_msv2_col]
711
710
  )
712
- xds["SOURCE_LOCATION"] = xr.DataArray(
711
+ xds["SOURCE_DIRECTION"] = xr.DataArray(
713
712
  direction_var.data, dims=direction_dims, attrs=location_msv4_measure
714
713
  )
715
714
 
@@ -739,14 +738,15 @@ def extract_source_info(
739
738
 
740
739
  # Need to add doppler info if present. Add check.
741
740
  try:
742
- doppler_xds = load_generic_table(
741
+ load_generic_table(
743
742
  path,
744
743
  "DOPPLER",
745
744
  )
746
- assert (
747
- False
748
- ), "Doppler table present. Please open an issue on https://github.com/casangi/xradio/issues so that we can add support for this."
749
- except:
745
+ logger.warning(
746
+ "Doppler table present. Please open an issue on "
747
+ "https://github.com/casangi/xradio/issues so that we can add support for this."
748
+ )
749
+ except ValueError:
750
750
  pass
751
751
 
752
752
  xds = xds.assign_coords(coords)
@@ -756,50 +756,6 @@ def extract_source_info(
756
756
  return xds, np.sum(num_lines[unique_source_ids_indices])
757
757
 
758
758
 
759
- def make_field_dims_and_coords(
760
- field_xds: xr.Dataset, field_id: Union[int, np.ndarray], field_times: list
761
- ) -> tuple[list, dict]:
762
- """
763
- Produces the dimensions and coordinates used in the field data variables
764
- extracted from the MSv2 FIELD subtable (FIELD_PHASE_CENTER/
765
- FIELD_REFERENCE_CENTER).
766
-
767
- Parameters:
768
- ----------
769
- field_xds: xr.Dataset
770
- generic field xarray dataset
771
- field_id: Union[int, np.ndarray]
772
- field_id of the dataset
773
- field_times:
774
- Unique times for the dataset (when not partitioning by FIELD_ID)
775
-
776
- Returns:
777
- -------
778
- tuple : tuple[list, dict]
779
- The dimensions and coordinates to use with field data variables. The
780
- dimensions are produced as a list of dimension names, and the
781
- coordinates as a dict for xarray coords.
782
- """
783
-
784
- coords = {"sky_dir_label": ["ra", "dec"]}
785
-
786
- # field_times is the same as the time axis in the main MSv4 dataset and is used if more than one field is present.
787
- if field_times is not None:
788
- coords["time"] = field_times
789
- dims = ["time", "sky_dir_label"]
790
- coords["field_name"] = (
791
- "time",
792
- np.char.add(field_xds["NAME"].data, np.char.add("_", field_id.astype(str))),
793
- )
794
- # coords["field_id"] = ("time", field_id)
795
- else:
796
- coords["field_name"] = field_xds["NAME"].values.item() + "_" + str(field_id)
797
- # coords["field_id"] = field_id
798
- dims = ["field_name", "sky_dir_label"]
799
-
800
- return dims, coords
801
-
802
-
803
759
  def extract_field_info_and_check_ephemeris(
804
760
  field_and_source_xds: xr.Dataset,
805
761
  in_file: str,
@@ -892,14 +848,17 @@ def extract_field_info_and_check_ephemeris(
892
848
  if is_single_dish:
893
849
  to_new_data_variables = {
894
850
  "REFERENCE_DIR": [
895
- "FIELD_REFERENCE_CENTER",
851
+ "FIELD_REFERENCE_CENTER_DIRECTION",
896
852
  ["field_name", "sky_dir_label"],
897
853
  ],
898
854
  "FIELD_ID": ["FIELD_ID", ["field_name"]],
899
855
  }
900
856
  else:
901
857
  to_new_data_variables = {
902
- "PHASE_DIR": ["FIELD_PHASE_CENTER", ["field_name", "sky_dir_label"]],
858
+ "PHASE_DIR": [
859
+ "FIELD_PHASE_CENTER_DIRECTION",
860
+ ["field_name", "sky_dir_label"],
861
+ ],
903
862
  # "DELAY_DIR": ["FIELD_DELAY_CENTER",["field_name", "sky_dir_label"]],
904
863
  # "REFERENCE_DIR": ["FIELD_REFERENCE_CENTER",["field_name", "sky_dir_label"]],
905
864
  }
@@ -937,59 +896,6 @@ def extract_field_info_and_check_ephemeris(
937
896
  # field_id shouldn ot be in final xds, and no longer needed past this point
938
897
  field_and_source_xds = field_and_source_xds.drop_vars("field_id")
939
898
 
940
- # dims, coords = make_field_dims_and_coords(field_xds, field_id, field_times)
941
-
942
- # if is_single_dish:
943
- # field_data_variables = {
944
- # "REFERENCE_DIR": "FIELD_REFERENCE_CENTER",
945
- # }
946
- # else:
947
- # field_data_variables = {
948
- # # "DELAY_DIR": "FIELD_DELAY_CENTER",
949
- # "PHASE_DIR": "FIELD_PHASE_CENTER",
950
- # # "REFERENCE_DIR": "FIELD_REFERENCE_CENTER",
951
- # }
952
-
953
- # field_column_description = field_xds.attrs["other"]["msv2"]["ctds_attrs"][
954
- # "column_descriptions"
955
- # ]
956
-
957
- # delay_dir_ref_col = "DelayDir_Ref"
958
- # if field_xds.get(delay_dir_ref_col) is None:
959
- # delaydir_ref = None
960
- # else:
961
- # delaydir_ref = check_if_consistent(
962
- # field_xds.get(delay_dir_ref_col), delay_dir_ref_col
963
- # )
964
-
965
- # for generic_name, msv4_name in field_data_variables.items():
966
- # msv4_measure = column_description_casacore_to_msv4_measure(
967
- # field_column_description[generic_name], ref_code=delaydir_ref
968
- # )
969
-
970
- # print(msv4_name,generic_name,field_xds[generic_name].data.shape,field_xds[generic_name].data)
971
-
972
- # field_and_source_xds[msv4_name] = xr.DataArray.from_dict(
973
- # {
974
- # "dims": dims,
975
- # "data": list(field_xds[generic_name].data),
976
- # "attrs": msv4_measure,
977
- # }
978
- # )
979
-
980
- # field_measures_type = "sky_coord"
981
- # field_and_source_xds[msv4_name].attrs["type"] = field_measures_type
982
-
983
- # field_and_source_xds = field_and_source_xds.assign_coords(coords)
984
- # if "time" in field_and_source_xds:
985
- # time_column_description = field_xds.attrs["other"]["msv2"]["ctds_attrs"][
986
- # "column_descriptions"
987
- # ]["TIME"]
988
- # time_msv4_measure = column_description_casacore_to_msv4_measure(
989
- # time_column_description
990
- # )
991
- # field_and_source_xds.coords["time"].attrs.update(time_msv4_measure)
992
-
993
899
  return (
994
900
  field_and_source_xds,
995
901
  ephemeris_path,
@@ -1,4 +1,3 @@
1
- import toolviper.utils.logger as logger
2
1
  from xradio._utils.schema import column_description_casacore_to_msv4_measure
3
2
 
4
3
  col_to_data_variable_names = {
@@ -39,6 +38,6 @@ def create_attribute_metadata(col, main_column_descriptions):
39
38
  if col in ["DATA", "CORRECTED_DATA", "WEIGHT"]:
40
39
  if not attrs_metadata:
41
40
  attrs_metadata["type"] = "quanta"
42
- attrs_metadata["units"] = ["unkown"]
41
+ attrs_metadata["units"] = "unkown"
43
42
 
44
43
  return attrs_metadata
@@ -10,7 +10,7 @@ import toolviper.utils.logger as logger
10
10
 
11
11
  from .subtables import subt_rename_ids
12
12
  from ._tables.read import load_generic_table, convert_casacore_time
13
- from xradio._utils.list_and_array import check_if_consistent, unique_1d, to_list
13
+ from xradio._utils.list_and_array import check_if_consistent
14
14
 
15
15
 
16
16
  def create_info_dicts(
@@ -47,12 +47,13 @@ def create_info_dicts(
47
47
  info dicts ready to be used to update the attrs of the MSv4
48
48
  """
49
49
 
50
- if "line_name" in field_and_source_xds.coords:
51
- line_name = to_list(unique_1d(np.ravel(field_and_source_xds.line_name.values)))
52
- else:
53
- line_name = []
54
-
55
50
  info_dicts = {}
51
+
52
+ # if "line_name" in field_and_source_xds.coords:
53
+ # line_name = to_list(unique_1d(np.ravel(field_and_source_xds.line_name.values)))
54
+ # else:
55
+ # line_name = []
56
+
56
57
  # info_dicts["partition_info"] = {
57
58
  # # "spectral_window_id": xds.frequency.attrs["spectral_window_id"],
58
59
  # "spectral_window_name": xds.frequency.attrs["spectral_window_name"],
@@ -125,7 +126,7 @@ def create_observation_info(in_file: str, observation_id: int):
125
126
  exec_block_xds = load_generic_table(in_file, "ASDM_EXECBLOCK")
126
127
  except ValueError as exc:
127
128
  logger.debug(
128
- "Did not find the ASDM_EXECBLOCK subtable, not loading optional fields in observation_info"
129
+ f"Did not find the ASDM_EXECBLOCK subtable, not loading optional fields in observation_info. Exception: {exc}"
129
130
  )
130
131
  if exec_block_xds:
131
132
  exec_block_info = extract_exec_block_info(exec_block_xds)