xradio 0.0.47__py3-none-any.whl → 0.0.49__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 (38) hide show
  1. xradio/__init__.py +1 -0
  2. xradio/_utils/dict_helpers.py +69 -2
  3. xradio/_utils/list_and_array.py +3 -1
  4. xradio/_utils/schema.py +3 -1
  5. xradio/image/_util/__init__.py +0 -3
  6. xradio/image/_util/_casacore/common.py +0 -13
  7. xradio/image/_util/_casacore/xds_from_casacore.py +102 -97
  8. xradio/image/_util/_casacore/xds_to_casacore.py +36 -24
  9. xradio/image/_util/_fits/xds_from_fits.py +81 -36
  10. xradio/image/_util/_zarr/zarr_low_level.py +3 -3
  11. xradio/image/_util/casacore.py +7 -5
  12. xradio/image/_util/common.py +13 -26
  13. xradio/image/_util/image_factory.py +143 -191
  14. xradio/image/image.py +10 -59
  15. xradio/measurement_set/__init__.py +11 -6
  16. xradio/measurement_set/_utils/_msv2/_tables/read.py +187 -46
  17. xradio/measurement_set/_utils/_msv2/_tables/table_query.py +22 -0
  18. xradio/measurement_set/_utils/_msv2/conversion.py +347 -299
  19. xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py +233 -150
  20. xradio/measurement_set/_utils/_msv2/descr.py +1 -1
  21. xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +20 -13
  22. xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +21 -22
  23. xradio/measurement_set/convert_msv2_to_processing_set.py +46 -6
  24. xradio/measurement_set/load_processing_set.py +100 -52
  25. xradio/measurement_set/measurement_set_xdt.py +197 -0
  26. xradio/measurement_set/open_processing_set.py +122 -86
  27. xradio/measurement_set/processing_set_xdt.py +1552 -0
  28. xradio/measurement_set/schema.py +375 -197
  29. xradio/schema/bases.py +5 -1
  30. xradio/schema/check.py +97 -5
  31. xradio/sphinx/schema_table.py +12 -0
  32. {xradio-0.0.47.dist-info → xradio-0.0.49.dist-info}/METADATA +4 -4
  33. {xradio-0.0.47.dist-info → xradio-0.0.49.dist-info}/RECORD +36 -36
  34. {xradio-0.0.47.dist-info → xradio-0.0.49.dist-info}/WHEEL +1 -1
  35. xradio/measurement_set/measurement_set_xds.py +0 -117
  36. xradio/measurement_set/processing_set.py +0 -777
  37. {xradio-0.0.47.dist-info → xradio-0.0.49.dist-info/licenses}/LICENSE.txt +0 -0
  38. {xradio-0.0.47.dist-info → xradio-0.0.49.dist-info}/top_level.txt +0 -0
@@ -19,19 +19,24 @@ def _compute_direction_dict(xds: xr.Dataset) -> dict:
19
19
  """
20
20
  direction = {}
21
21
  xds_dir = xds.attrs["direction"]
22
- direction["system"] = xds_dir["reference"]["equinox"]
22
+ direction["system"] = xds_dir["reference"]["attrs"]["equinox"].upper()
23
+ if direction["system"] == "J2000.0":
24
+ direction["system"] = "J2000"
23
25
  direction["projection"] = xds_dir["projection"]
24
26
  direction["projection_parameters"] = xds_dir["projection_parameters"]
25
- direction["units"] = np.array(xds_dir["reference"]["units"], dtype="<U16")
26
- direction["crval"] = np.array(xds_dir["reference"]["value"])
27
- direction["cdelt"] = np.array((xds.l.cdelt, xds.m.cdelt))
27
+ direction["units"] = np.array(xds_dir["reference"]["attrs"]["units"], dtype="<U16")
28
+ direction["crval"] = np.array(xds_dir["reference"]["data"])
29
+ direction["cdelt"] = np.array((xds.l[1] - xds.l[0], xds.m[1] - xds.m[0]))
28
30
  direction["crpix"] = _compute_sky_reference_pixel(xds)
29
31
  direction["pc"] = np.array(xds_dir["pc"])
30
32
  direction["axes"] = ["Right Ascension", "Declination"]
31
33
  direction["conversionSystem"] = direction["system"]
32
34
  for s in ["longpole", "latpole"]:
33
- # longpole, latpole are numerical values in degrees in casa images
34
- direction[s] = Angle(str(xds_dir[s]["value"]) + xds_dir[s]["units"]).deg
35
+ m = "lonpole" if s == "longpole" else s
36
+ # lonpole, latpole are numerical values in degrees in casa images
37
+ direction[s] = Angle(
38
+ str(xds_dir[m]["data"]) + xds_dir[m]["attrs"]["units"][0]
39
+ ).deg
35
40
  return direction
36
41
 
37
42
 
@@ -69,20 +74,22 @@ def _compute_spectral_dict(xds: xr.Dataset) -> dict:
69
74
  # spec["nativeType"] = _native_types.index(xds.frequency.attrs["native_type"])
70
75
  # FREQ
71
76
  spec["nativeType"] = 0
72
- spec["restfreq"] = xds.frequency.attrs["rest_frequency"]["value"]
77
+ spec["restfreq"] = xds.frequency.attrs["rest_frequency"]["data"]
73
78
  # spec["restfreqs"] = copy.deepcopy(xds.frequency.attrs["restfreqs"]["value"])
74
79
  spec["restfreqs"] = [spec["restfreq"]]
75
- spec["system"] = xds.frequency.attrs["frame"]
76
- spec["unit"] = xds.frequency.attrs["units"]
80
+ spec["system"] = xds.frequency.attrs["reference_value"]["attrs"]["observer"].upper()
81
+ u = xds.frequency.attrs["reference_value"]["attrs"]["units"]
82
+ spec["unit"] = u if isinstance(u, str) else u[0]
77
83
  spec["velType"] = _doppler_types.index(xds.velocity.attrs["doppler_type"])
78
- spec["velUnit"] = xds.velocity.attrs["units"]
84
+ u = xds.velocity.attrs["units"]
85
+ spec["velUnit"] = u if isinstance(u, str) else u[0]
79
86
  spec["version"] = 2
80
87
  spec["waveUnit"] = xds.frequency.attrs["wave_unit"]
81
88
  wcs = {}
82
89
  wcs["ctype"] = "FREQ"
83
90
  wcs["pc"] = 1.0
84
- wcs["crval"] = xds.frequency.attrs["crval"]
85
- wcs["cdelt"] = xds.frequency.attrs["cdelt"]
91
+ wcs["crval"] = xds.frequency.attrs["reference_value"]["data"]
92
+ wcs["cdelt"] = xds.frequency.values[1] - xds.frequency.values[0]
86
93
  wcs["crpix"] = (wcs["crval"] - xds.frequency.values[0]) / wcs["cdelt"]
87
94
  spec["wcs"] = wcs
88
95
  return spec
@@ -96,7 +103,7 @@ def _coord_dict_from_xds(xds: xr.Dataset) -> dict:
96
103
  obsdate["refer"] = xds.coords["time"].attrs["scale"]
97
104
  obsdate["type"] = "epoch"
98
105
  obsdate["m0"] = {}
99
- obsdate["m0"]["unit"] = xds.coords["time"].attrs["units"]
106
+ obsdate["m0"]["unit"] = xds.coords["time"].attrs["units"][0]
100
107
  obsdate["m0"]["value"] = xds.coords["time"].values[0]
101
108
  coord["obsdate"] = obsdate
102
109
  coord["pointingcenter"] = xds.attrs[_pointing_center].copy()
@@ -137,7 +144,8 @@ def _coord_dict_from_xds(xds: xr.Dataset) -> dict:
137
144
  # this probbably needs some verification
138
145
  coord["worldreplace0"] = [0.0, 0.0]
139
146
  coord["worldreplace1"] = np.array(coord["stokes1"]["crval"])
140
- coord["worldreplace2"] = np.array([xds.frequency.attrs["crval"]])
147
+ # print("spectral", coord["spectral2"])
148
+ coord["worldreplace2"] = np.array(coord["spectral2"]["wcs"]["crval"])
141
149
  return coord
142
150
 
143
151
 
@@ -174,17 +182,17 @@ def _imageinfo_dict_from_xds(xds: xr.Dataset) -> dict:
174
182
  xds[ap_sky].attrs["image_type"] if "image_type" in xds[ap_sky].attrs else ""
175
183
  )
176
184
  ii["objectname"] = xds.attrs[_object_name]
177
- if "beam" in xds.data_vars:
185
+ if "BEAM" in xds.data_vars:
178
186
  # multi beam
179
187
  pp = {}
180
- pp["nChannels"] = len(xds.frequency)
181
- pp["nStokes"] = len(xds.polarization)
182
- bu = xds.beam.attrs["units"]
188
+ pp["nChannels"] = xds.sizes["frequency"]
189
+ pp["nStokes"] = xds.sizes["polarization"]
190
+ bu = xds.BEAM.attrs["units"]
183
191
  chan = 0
184
192
  polarization = 0
185
- bv = xds.beam.values
193
+ bv = xds.BEAM.values
186
194
  for i in range(pp["nChannels"] * pp["nStokes"]):
187
- bp = bv[0][polarization][chan][:]
195
+ bp = bv[0][chan][polarization][:]
188
196
  b = {
189
197
  "major": {"unit": bu, "value": bp[0]},
190
198
  "minor": {"unit": bu, "value": bp[1]},
@@ -196,15 +204,20 @@ def _imageinfo_dict_from_xds(xds: xr.Dataset) -> dict:
196
204
  chan = 0
197
205
  polarization += 1
198
206
  ii["perplanebeams"] = pp
207
+ """
199
208
  elif "beam" in xds.attrs and xds.attrs["beam"]:
200
209
  # do nothing if xds.attrs['beam'] is None
201
210
  ii["restoringbeam"] = copy.deepcopy(xds.attrs["beam"])
202
211
  for k in ["major", "minor", "pa"]:
203
- del ii["restoringbeam"][k]["type"]
204
- ii["restoringbeam"][k]["unit"] = ii["restoringbeam"][k]["units"]
205
- del ii["restoringbeam"][k]["units"]
212
+ # print("*** ", k, ii["restoringbeam"][k])
213
+ del ii["restoringbeam"][k]["dims"]
214
+ ii["restoringbeam"][k]["unit"] = ii["restoringbeam"][k]["attrs"]["units"][0]
215
+ del ii["restoringbeam"][k]["attrs"]
216
+ ii["restoringbeam"][k]["value"] = ii["restoringbeam"][k]["data"]
217
+ del ii["restoringbeam"][k]["data"]
206
218
  ii["restoringbeam"]["positionangle"] = copy.deepcopy(ii["restoringbeam"]["pa"])
207
219
  del ii["restoringbeam"]["pa"]
220
+ """
208
221
  return ii
209
222
 
210
223
 
@@ -319,7 +332,6 @@ def _write_initial_image(
319
332
  if xds[dv][0, 0, 0, 0, 0].values.dtype == "float32":
320
333
  value = "default"
321
334
  break
322
- # print(type(value))
323
335
  image_full_path = os.path.expanduser(imagename)
324
336
  with _create_new_image(
325
337
  image_full_path, mask=maskname, shape=image_shape, value=value
@@ -16,7 +16,11 @@ from ..common import (
16
16
  _l_m_attr_notes,
17
17
  )
18
18
  from xradio._utils.coord_math import _deg_to_rad
19
- from xradio._utils.dict_helpers import make_quantity
19
+ from xradio._utils.dict_helpers import (
20
+ make_quantity,
21
+ make_frequency_reference_dict,
22
+ make_skycoord_dict,
23
+ )
20
24
  import copy
21
25
  import dask
22
26
  import dask.array as da
@@ -50,6 +54,8 @@ def _fits_image_to_xds(
50
54
  xds = _add_coord_attrs(xds, helpers)
51
55
  if helpers["has_multibeam"]:
52
56
  xds = _do_multibeam(xds, img_full_path)
57
+ elif "beam" in helpers and helpers["beam"] is not None:
58
+ xds = _add_beam(xds, helpers)
53
59
  return xds
54
60
 
55
61
 
@@ -66,6 +72,7 @@ def _add_time_attrs(xds: xr.Dataset, helpers: dict) -> xr.Dataset:
66
72
  time_coord = xds.coords["time"]
67
73
  meta = copy.deepcopy(helpers["obsdate"])
68
74
  del meta["value"]
75
+ # meta["units"] = [ meta["units"] ]
69
76
  # meta['format'] = 'MJD'
70
77
  # meta['time_scale'] = meta['refer']
71
78
  # del meta['refer']
@@ -79,13 +86,16 @@ def _add_freq_attrs(xds: xr.Dataset, helpers: dict) -> xr.Dataset:
79
86
  meta = {}
80
87
  if helpers["has_freq"]:
81
88
  meta["rest_frequency"] = make_quantity(helpers["restfreq"], "Hz")
82
- meta["frame"] = helpers["specsys"]
83
- meta["units"] = "Hz"
89
+ meta["rest_frequencies"] = [meta["rest_frequency"]]
90
+ # meta["frame"] = helpers["specsys"]
91
+ # meta["units"] = "Hz"
84
92
  meta["type"] = "frequency"
85
93
  meta["wave_unit"] = "mm"
86
94
  freq_axis = helpers["freq_axis"]
87
- meta["crval"] = helpers["crval"][freq_axis]
88
- meta["cdelt"] = helpers["cdelt"][freq_axis]
95
+ meta["reference_value"] = make_frequency_reference_dict(
96
+ helpers["crval"][freq_axis], ["Hz"], helpers["specsys"]
97
+ )
98
+ # meta["cdelt"] = helpers["cdelt"][freq_axis]
89
99
  if not meta:
90
100
  # this is the default frequency information CASA creates
91
101
  meta = _default_freq_info()
@@ -96,7 +106,7 @@ def _add_freq_attrs(xds: xr.Dataset, helpers: dict) -> xr.Dataset:
96
106
 
97
107
  def _add_vel_attrs(xds: xr.Dataset, helpers: dict) -> xr.Dataset:
98
108
  vel_coord = xds.coords["velocity"]
99
- meta = {"units": "m/s"}
109
+ meta = {"units": ["m/s"]}
100
110
  if helpers["has_freq"]:
101
111
  meta["doppler_type"] = helpers.get("doppler", "RADIO")
102
112
  else:
@@ -112,10 +122,6 @@ def _add_l_m_attrs(xds: xr.Dataset, helpers: dict) -> xr.Dataset:
112
122
  for c in ["l", "m"]:
113
123
  if c in xds.coords:
114
124
  xds[c].attrs = {
115
- "crval": 0.0,
116
- "cdelt": helpers[c]["cdelt"],
117
- "units": "rad",
118
- "type": "quantity",
119
125
  "note": attr_note[c],
120
126
  }
121
127
  return xds
@@ -167,6 +173,10 @@ def _xds_direction_attrs_from_header(helpers: dict, header) -> dict:
167
173
  helpers["ref_sys"] = ref_sys
168
174
  helpers["ref_eqx"] = ref_eqx
169
175
  # fits does not support conversion frames
176
+ direction["reference"] = make_skycoord_dict(
177
+ [0.0, 0.0], units=["rad", "rad"], frame=ref_sys
178
+ )
179
+ """
170
180
  direction["reference"] = {
171
181
  "type": "sky_coord",
172
182
  "frame": ref_sys,
@@ -174,20 +184,39 @@ def _xds_direction_attrs_from_header(helpers: dict, header) -> dict:
174
184
  "units": ["rad", "rad"],
175
185
  "value": [0.0, 0.0],
176
186
  }
187
+ """
177
188
  dir_axes = helpers["dir_axes"]
189
+ ddata = []
190
+ dunits = []
178
191
  for i in dir_axes:
179
192
  x = helpers["crval"][i] * u.Unit(_get_unit(helpers["cunit"][i]))
180
193
  x = x.to("rad")
181
- direction["reference"]["value"][i] = x.value
194
+ ddata.append(x.value)
195
+ # direction["reference"]["value"][i] = x.value
182
196
  x = helpers["cdelt"][i] * u.Unit(_get_unit(helpers["cunit"][i]))
183
- x = x.to("rad")
184
- direction["latpole"] = make_quantity(header["LATPOLE"] * _deg_to_rad, "rad")
185
- direction["longpole"] = make_quantity(header["LONPOLE"] * _deg_to_rad, "rad")
197
+ dunits.append(x.to("rad"))
198
+ direction["reference"] = make_skycoord_dict(ddata, units=dunits, frame=ref_sys)
199
+ direction["reference"]["attrs"]["equinox"] = ref_eqx.lower()
200
+ direction["latpole"] = make_quantity(
201
+ header["LATPOLE"] * _deg_to_rad, "rad", dims=["l", "m"]
202
+ )
203
+ direction["lonpole"] = make_quantity(
204
+ header["LONPOLE"] * _deg_to_rad, "rad", dims=["l", "m"]
205
+ )
186
206
  pc = np.zeros([2, 2])
187
207
  for i in (0, 1):
188
208
  for j in (0, 1):
189
209
  # dir_axes are now 0-based, but fits needs 1-based
190
- pc[i][j] = header[f"PC{dir_axes[i]+1}_{dir_axes[j]+1}"]
210
+ try:
211
+ pc[i][j] = header[f"PC{dir_axes[i]+1}_{dir_axes[j]+1}"]
212
+ except KeyError:
213
+ try:
214
+ pc[i][j] = header[f"PC0{dir_axes[i]+1}_0{dir_axes[j]+1}"]
215
+ except KeyError:
216
+ raise RuntimeError(
217
+ f"Could not find PC{dir_axes[i]+1}_{dir_axes[j]+1} or "
218
+ f"PC0{dir_axes[i]+1}_0{dir_axes[j]+1} in FITS header"
219
+ )
191
220
  direction["pc"] = pc
192
221
  # Is there really no fits header parameter for projection_parameters?
193
222
  direction["projection_parameters"] = np.array([0.0, 0.0])
@@ -314,9 +343,9 @@ def _beam_attr_from_header(helpers: dict, header) -> Union[dict, str, None]:
314
343
  if "BMAJ" in header:
315
344
  # single global beam
316
345
  beam = {
317
- "bmaj": make_quantity(header["BMAJ"], "arcsec"),
318
- "bmin": make_quantity(header["BMIN"], "arcsec"),
319
- "pa": make_quantity(header["BPA"], "arcsec"),
346
+ "bmaj": make_quantity(header["BMAJ"], "deg"),
347
+ "bmin": make_quantity(header["BMIN"], "deg"),
348
+ "pa": make_quantity(header["BPA"], "deg"),
320
349
  }
321
350
  return _convert_beam_to_rad(beam)
322
351
  elif "CASAMBM" in header and header["CASAMBM"]:
@@ -390,11 +419,11 @@ def _fits_header_to_xds_attrs(hdulist: fits.hdu.hdulist.HDUList) -> dict:
390
419
  attrs["direction"] = _xds_direction_attrs_from_header(helpers, header)
391
420
  # FIXME read fits data in chunks in case all data too large to hold in memory
392
421
  has_mask = da.any(da.isnan(primary.data)).compute()
393
- attrs["active_mask"] = "mask0" if has_mask else None
422
+ attrs["active_mask"] = "MASK0" if has_mask else None
394
423
  helpers["has_mask"] = has_mask
395
424
  beam = _beam_attr_from_header(helpers, header)
396
425
  if beam != "mb":
397
- attrs["beam"] = beam
426
+ helpers["beam"] = beam
398
427
  if "BITPIX" in header:
399
428
  v = abs(header["BITPIX"])
400
429
  if v == 32:
@@ -409,7 +438,7 @@ def _fits_header_to_xds_attrs(hdulist: fits.hdu.hdulist.HDUList) -> dict:
409
438
  obsdate = {}
410
439
  obsdate["type"] = "time"
411
440
  obsdate["value"] = Time(header["DATE-OBS"], format="isot").mjd
412
- obsdate["units"] = "d"
441
+ obsdate["units"] = ["d"]
413
442
  obsdate["scale"] = header["TIMESYS"]
414
443
  obsdate["format"] = "MJD"
415
444
  attrs["obsdate"] = obsdate
@@ -453,8 +482,8 @@ def _create_coords(
453
482
  helpers["sphr_dims"] = sphr_dims
454
483
  coords = {}
455
484
  coords["time"] = _get_time_values(helpers)
456
- coords["polarization"] = _get_pol_values(helpers)
457
485
  coords["frequency"] = _get_freq_values(helpers)
486
+ coords["polarization"] = _get_pol_values(helpers)
458
487
  coords["velocity"] = (["frequency"], _get_velocity_values(helpers))
459
488
  if len(sphr_dims) > 0:
460
489
  for i, c in enumerate(["l", "m"]):
@@ -497,6 +526,7 @@ def _create_coords(
497
526
  else:
498
527
  # Fourier image
499
528
  coords["u"], coords["v"] = _get_uv_values(helpers)
529
+ coords["beam_param"] = ["major", "minor", "pa"]
500
530
  xds = xr.Dataset(coords=coords)
501
531
  return xds
502
532
 
@@ -615,28 +645,43 @@ def _do_multibeam(xds: xr.Dataset, imname: str) -> xr.Dataset:
615
645
  )
616
646
  nchan = header["NCHAN"]
617
647
  npol = header["NPOL"]
618
- beam_array = np.zeros([1, npol, nchan, 3])
648
+ beam_array = np.zeros([1, nchan, npol, 3])
619
649
  data = hdu.data
650
+ hdulist.close()
620
651
  for t in data:
621
- beam_array[0, t[4], t[3]] = t[0:3]
652
+ beam_array[0, t[3], t[4]] = t[0:3]
622
653
  for i in (0, 1, 2):
623
654
  beam_array[:, :, :, i] = (
624
655
  (beam_array[:, :, :, i] * units[i]).to("rad").value
625
656
  )
626
- xdb = xr.DataArray(
627
- beam_array, dims=["time", "polarization", "frequency", "beam_param"]
628
- )
629
- xdb = xdb.rename("beam")
630
- xdb = xdb.assign_coords(beam_param=["major", "minor", "pa"])
631
- xdb.attrs["units"] = "rad"
632
- xds["beam"] = xdb
633
- return xds
657
+ return _create_beam_data_var(xds, beam_array)
634
658
  raise RuntimeError(
635
659
  "It looks like there should be a BEAMS table but no "
636
660
  "such table found in FITS file"
637
661
  )
638
662
 
639
663
 
664
+ def _add_beam(xds: xr.Dataset, helpers: dict) -> xr.Dataset:
665
+ nchan = xds.sizes["frequency"]
666
+ npol = xds.sizes["polarization"]
667
+ beam_array = np.zeros([1, nchan, npol, 3])
668
+ beam_array[0, :, :, 0] = helpers["beam"]["bmaj"]["data"]
669
+ beam_array[0, :, :, 1] = helpers["beam"]["bmin"]["data"]
670
+ beam_array[0, :, :, 2] = helpers["beam"]["pa"]["data"]
671
+ return _create_beam_data_var(xds, beam_array)
672
+
673
+
674
+ def _create_beam_data_var(xds: xr.Dataset, beam_array: np.array) -> xr.Dataset:
675
+ xdb = xr.DataArray(
676
+ beam_array, dims=["time", "frequency", "polarization", "beam_param"]
677
+ )
678
+ xdb = xdb.rename("BEAM")
679
+ xdb = xdb.assign_coords(beam_param=["major", "minor", "pa"])
680
+ xdb.attrs["units"] = "rad"
681
+ xds["BEAM"] = xdb
682
+ return xds
683
+
684
+
640
685
  def _get_uv_values(helpers: dict) -> tuple:
641
686
  shape = helpers["shape"]
642
687
  ctype = helpers["ctype"]
@@ -680,8 +725,8 @@ def _add_sky_or_aperture(
680
725
  pp = da if type(xda[0].data) == dask.array.core.Array else np
681
726
  mask = pp.isnan(xda)
682
727
  mask.attrs = {}
683
- mask = mask.rename("mask0")
684
- xds["mask0"] = mask
728
+ mask = mask.rename("MASK0")
729
+ xds["MASK0"] = mask
685
730
  return xds
686
731
 
687
732
 
@@ -790,10 +835,10 @@ def _get_transpose_list(helpers: dict) -> tuple:
790
835
  or b.startswith("vopt")
791
836
  or b.startswith("vrad")
792
837
  ):
793
- transpose_list[2] = i
838
+ transpose_list[1] = i
794
839
  not_covered.remove("f")
795
840
  elif b.startswith("stok"):
796
- transpose_list[1] = i
841
+ transpose_list[2] = i
797
842
  not_covered.remove("s")
798
843
  else:
799
844
  raise RuntimeError(f"Unhandled axis name {c}")
@@ -12,9 +12,9 @@ from numcodecs.compat import (
12
12
  ensure_contiguous_ndarray_like,
13
13
  )
14
14
 
15
- full_dims_lm = ["time", "polarization", "frequency", "l", "m"]
16
- full_dims_uv = ["time", "polarization", "frequency", "l", "m"]
17
- norm_dims = ["polarization", "frequency"]
15
+ full_dims_lm = ["time", "frequency", "polarization", "l", "m"]
16
+ full_dims_uv = ["time", "frequency", "polarization", "l", "m"]
17
+ norm_dims = ["frequency", "polarization"]
18
18
 
19
19
  image_data_variables_and_dims_double_precision = {
20
20
  "aperture": {"dims": full_dims_uv, "dtype": "<c16", "name": "APERTURE"},
@@ -55,15 +55,16 @@ def _load_casa_image_block(infile: str, block_des: dict, do_sky_coords) -> xr.Da
55
55
  block = _get_persistent_block(
56
56
  full_path, shapes, starts, dimorder, transpose_list, new_axes
57
57
  )
58
- xds = _add_mask(xds, m, block, dimorder)
58
+ # data vars are all caps by convention
59
+ xds = _add_mask(xds, m.upper(), block, dimorder)
59
60
  xds.attrs = _casa_image_to_xds_attrs(image_full_path, True)
60
61
  mb = _multibeam_array(xds, image_full_path, False)
61
62
  if mb is not None:
62
63
  selectors = {}
63
- for k in ("time", "polarization", "frequency"):
64
+ for k in ("time", "frequency", "polarization"):
64
65
  if k in block_des:
65
66
  selectors[k] = block_des[k]
66
- xds["beam"] = mb.isel(selectors)
67
+ xds["BEAM"] = mb.isel(selectors)
67
68
  return xds
68
69
 
69
70
 
@@ -90,11 +91,12 @@ def _read_casa_image(
90
91
  mymasks = _get_mask_names(img_full_path)
91
92
  for m in mymasks:
92
93
  ary = _read_image_array(img_full_path, chunks, mask=m, verbose=verbose)
93
- xds = _add_mask(xds, m, ary, dimorder)
94
+ # data var names are all caps by convention
95
+ xds = _add_mask(xds, m.upper(), ary, dimorder)
94
96
  xds.attrs = _casa_image_to_xds_attrs(img_full_path, history)
95
97
  mb = _multibeam_array(xds, img_full_path, True)
96
98
  if mb is not None:
97
- xds["beam"] = mb
99
+ xds["BEAM"] = mb
98
100
  # xds = _add_coord_attrs(xds, ret["icoords"], ret["dir_axes"])
99
101
  xds = _dask_arrayize_dv(xds)
100
102
  return xds
@@ -10,7 +10,13 @@ from xradio._utils.dict_helpers import make_quantity
10
10
 
11
11
  _c = 2.99792458e08 * u.m / u.s
12
12
  # OPTICAL = Z
13
- _doppler_types = ["RADIO", "Z", "RATIO", "BETA", "GAMMA"]
13
+ _doppler_types = [
14
+ "radio",
15
+ "z",
16
+ "ratio",
17
+ "beta",
18
+ "gamma",
19
+ ]
14
20
  _image_type = "image_type"
15
21
 
16
22
 
@@ -19,7 +25,7 @@ def _aperture_or_sky(xds: xr.Dataset) -> str:
19
25
 
20
26
 
21
27
  def _get_xds_dim_order(has_sph: bool) -> list:
22
- dimorder = ["time", "polarization", "frequency"]
28
+ dimorder = ["time", "frequency", "polarization"]
23
29
  dir_lin = ["l", "m"] if has_sph else ["u", "v"]
24
30
  dimorder.extend(dir_lin)
25
31
  return dimorder
@@ -34,10 +40,10 @@ def _convert_beam_to_rad(beam: dict) -> dict:
34
40
  """
35
41
  mybeam = {}
36
42
  for k in beam:
37
- try:
38
- q = u.quantity.Quantity(f"{beam[k]['value']}{beam[k]['unit']}")
39
- except:
40
- q = u.quantity.Quantity(f"{beam[k]['value']}{beam[k]['units']}")
43
+ myu = beam[k]["attrs"]["units"]
44
+ myu = myu[0] if isinstance(myu, list) else myu
45
+ units = _get_unit(myu)
46
+ q = u.quantity.Quantity(f"{beam[k]['data']}{units}")
41
47
  q = q.to("rad")
42
48
  j = "pa" if k == "positionangle" else k
43
49
  mybeam[j] = make_quantity(q.value, "rad")
@@ -105,7 +111,7 @@ def _default_freq_info() -> dict:
105
111
  return {
106
112
  "rest_frequency": make_quantity(1420405751.7860003, "Hz"),
107
113
  "type": "frequency",
108
- "frame": "LSRK",
114
+ "frame": "lsrk",
109
115
  "units": "Hz",
110
116
  "waveUnit": "mm",
111
117
  "cdelt": 1000.0,
@@ -253,22 +259,3 @@ def _l_m_attr_notes() -> Dict[str, str]:
253
259
  "So m = y*cdelt, where y is the number of pixels from the phase center. "
254
260
  "See AIPS Memo #27, Section III.",
255
261
  }
256
-
257
-
258
- def _set_multibeam_array(xds, beam_ary, units):
259
- if "beam" in xds.attrs:
260
- if xds.attrs["beam"] is None:
261
- del xds.attrs["beam"]
262
- else:
263
- raise RuntimeError(
264
- "Error: xds has beam attr. It must be removed "
265
- "before multiple beams can be added"
266
- )
267
- xdb = xr.DataArray(
268
- beam_ary, dims=["time", "polarization", "frequency", "beam_param"]
269
- )
270
- xdb = xdb.rename("beam")
271
- xdb = xdb.assign_coords(beam_param=["major", "minor", "pa"])
272
- xdb.attrs["units"] = units
273
- xds["beam"] = xdb
274
- return xds