xradio 0.0.54__py3-none-any.whl → 0.0.56__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 (26) hide show
  1. xradio/_utils/_casacore/casacore_from_casatools.py +991 -0
  2. xradio/_utils/_casacore/tables.py +5 -1
  3. xradio/image/_util/_casacore/common.py +11 -3
  4. xradio/image/_util/_casacore/xds_from_casacore.py +45 -46
  5. xradio/image/_util/_casacore/xds_to_casacore.py +6 -2
  6. xradio/image/_util/_fits/xds_from_fits.py +27 -43
  7. xradio/image/_util/casacore.py +21 -12
  8. xradio/image/image.py +1 -1
  9. xradio/measurement_set/_utils/_msv2/_tables/load.py +4 -1
  10. xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py +4 -1
  11. xradio/measurement_set/_utils/_msv2/_tables/read.py +18 -14
  12. xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py +4 -1
  13. xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py +4 -1
  14. xradio/measurement_set/_utils/_msv2/_tables/table_query.py +13 -3
  15. xradio/measurement_set/_utils/_msv2/_tables/write.py +4 -1
  16. xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py +4 -1
  17. xradio/measurement_set/_utils/_msv2/conversion.py +7 -1
  18. xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +5 -1
  19. xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +1 -1
  20. xradio/measurement_set/_utils/_msv2/partition_queries.py +4 -1
  21. xradio/measurement_set/schema.py +3 -3
  22. {xradio-0.0.54.dist-info → xradio-0.0.56.dist-info}/METADATA +42 -11
  23. {xradio-0.0.54.dist-info → xradio-0.0.56.dist-info}/RECORD +26 -25
  24. {xradio-0.0.54.dist-info → xradio-0.0.56.dist-info}/WHEEL +1 -1
  25. {xradio-0.0.54.dist-info → xradio-0.0.56.dist-info}/licenses/LICENSE.txt +0 -0
  26. {xradio-0.0.54.dist-info → xradio-0.0.56.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,8 @@
1
- from casacore import tables
1
+ try:
2
+ from casacore import tables
3
+ except ImportError:
4
+ import xradio._utils._casacore.casacore_from_casatools as tables
5
+
2
6
  from contextlib import contextmanager
3
7
  from typing import Dict, Generator
4
8
 
@@ -1,7 +1,10 @@
1
- from casacore import images
1
+ try:
2
+ from casacore import images
3
+ except ImportError:
4
+ import xradio._utils._casacore.casacore_from_casatools as images
5
+
2
6
  from contextlib import contextmanager
3
- import numpy as np
4
- from typing import Dict, Generator, List, Union
7
+ from typing import Generator, List
5
8
 
6
9
 
7
10
  @contextmanager
@@ -12,6 +15,7 @@ def _open_image_ro(infile: str) -> Generator[images.image, None, None]:
12
15
  finally:
13
16
  # there is no obvious way to close a python-casacore image, so
14
17
  # just delete the object to clear it from the table cache
18
+ # image.unlock() # not necessary
15
19
  del image
16
20
 
17
21
 
@@ -31,6 +35,10 @@ def _create_new_image(
31
35
  try:
32
36
  yield image
33
37
  finally:
38
+ # Explicitly calling unlock() is important for downstream parallel reads across multiple processes.
39
+ # Without it, Dask workers may mistakenly consider a freshly written image from another process
40
+ # as invalid—even if the image directory appears to be fully written and present.
41
+ image.unlock()
34
42
  del image
35
43
 
36
44
 
@@ -9,8 +9,15 @@ import toolviper.utils.logger as logger
9
9
  import numpy as np
10
10
  import xarray as xr
11
11
  from astropy import units as u
12
- from casacore import tables
13
- from casacore.images import coordinates, image as casa_image
12
+
13
+ try:
14
+ from casacore import tables
15
+ from casacore.images import coordinates, image as casa_image
16
+ except ImportError:
17
+ import xradio._utils._casacore.casacore_from_casatools as tables
18
+ import xradio._utils._casacore.casacore_from_casatools as coordinates
19
+ from xradio._utils._casacore.casacore_from_casatools import image as casa_image
20
+
14
21
 
15
22
  from .common import (
16
23
  _active_mask,
@@ -18,6 +25,7 @@ from .common import (
18
25
  _open_image_ro,
19
26
  _pointing_center,
20
27
  )
28
+
21
29
  from ..common import (
22
30
  _compute_linear_world_values,
23
31
  _compute_velocity_values,
@@ -599,36 +607,6 @@ def _get_mask_names(infile: str) -> list:
599
607
  return mymasks
600
608
 
601
609
 
602
- def _get_beam(imageinfo: dict, nchan: int, npol: int) -> Union[np.ndarray, None]:
603
- """Returns None if the image has no beam(s)"""
604
- x = ["perplanebeams", "restoringbeam"]
605
- r = None
606
- for z in x:
607
- if z in imageinfo:
608
- r = z
609
- break
610
- if r is None:
611
- return None
612
- beam = imageinfo[r]
613
- beam_array = np.zeros([1, nchan, npol, 3])
614
- if r == "perplanebeams":
615
- for c in range(nchan):
616
- for p in range(npol):
617
- k = nchan * p + c
618
- b = _casacore_q_to_xradio_q(beam["*" + str(k)])
619
- beam_dict = _convert_beam_to_rad(b)
620
- beam_array[0][c][p][0] = beam_dict["major"]["data"]
621
- beam_array[0][c][p][1] = beam_dict["minor"]["data"]
622
- beam_array[0][c][p][2] = beam_dict["pa"]["data"]
623
- elif r == "restoringbeam":
624
- b = _casacore_q_to_xradio_q(beam)
625
- beam_dict = _convert_beam_to_rad(b)
626
- beam_array[0, :, :, 0] = beam_dict["major"]["data"]
627
- beam_array[0, :, :, 1] = beam_dict["minor"]["data"]
628
- beam_array[0, :, :, 2] = beam_dict["pa"]["data"]
629
- return beam_array
630
-
631
-
632
610
  def _get_persistent_block(
633
611
  infile: str,
634
612
  shapes: tuple,
@@ -834,25 +812,46 @@ def _get_velocity_values_attrs(
834
812
  )
835
813
 
836
814
 
837
- def _multibeam_array(
838
- xds: xr.Dataset, img_full_path: str, as_dask_array: bool
815
+ def _get_beam(
816
+ img_full_path: str, nchan: int, npol: int, as_dask_array: bool
839
817
  ) -> Union[xr.DataArray, None]:
840
818
  # the image may have multiple beams
841
819
  with _open_image_ro(img_full_path) as casa_image:
842
820
  imageinfo = casa_image.info()["imageinfo"]
843
- mb = _get_beam(
844
- imageinfo, nchan=xds.sizes["frequency"], npol=xds.sizes["polarization"]
845
- )
846
- if mb is not None:
847
- if as_dask_array:
848
- mb = da.array(mb)
849
- xdb = xr.DataArray(mb, dims=["time", "frequency", "polarization", "beam_param"])
850
- xdb = xdb.rename("BEAM")
851
- xdb = xdb.assign_coords(beam_param=["major", "minor", "pa"])
852
- xdb.attrs["units"] = "rad"
853
- return xdb
854
- else:
821
+ x = ["perplanebeams", "restoringbeam"]
822
+ r = None
823
+ for z in x:
824
+ if z in imageinfo:
825
+ r = z
826
+ break
827
+ if r is None:
855
828
  return None
829
+ beam = imageinfo[r]
830
+ beam_array = np.zeros([1, nchan, npol, 3])
831
+ if r == "perplanebeams":
832
+ for c in range(nchan):
833
+ for p in range(npol):
834
+ k = nchan * p + c
835
+ b = _casacore_q_to_xradio_q(beam["*" + str(k)])
836
+ beam_dict = _convert_beam_to_rad(b)
837
+ beam_array[0][c][p][0] = beam_dict["major"]["data"]
838
+ beam_array[0][c][p][1] = beam_dict["minor"]["data"]
839
+ beam_array[0][c][p][2] = beam_dict["pa"]["data"]
840
+ elif r == "restoringbeam":
841
+ b = _casacore_q_to_xradio_q(beam)
842
+ beam_dict = _convert_beam_to_rad(b)
843
+ beam_array[0, :, :, 0] = beam_dict["major"]["data"]
844
+ beam_array[0, :, :, 1] = beam_dict["minor"]["data"]
845
+ beam_array[0, :, :, 2] = beam_dict["pa"]["data"]
846
+ if as_dask_array:
847
+ beam_array = da.array(beam_array)
848
+ xdb = xr.DataArray(
849
+ beam_array, dims=["time", "frequency", "polarization", "beam_param"]
850
+ )
851
+ xdb = xdb.rename("BEAM")
852
+ xdb = xdb.assign_coords(beam_param=["major", "minor", "pa"])
853
+ xdb.attrs["units"] = "rad"
854
+ return xdb
856
855
 
857
856
 
858
857
  ###########################################################################
@@ -5,7 +5,11 @@ import dask.array as da
5
5
  import numpy as np
6
6
  import xarray as xr
7
7
  from astropy.coordinates import Angle
8
- from casacore import tables
8
+
9
+ try:
10
+ from casacore import tables
11
+ except ImportError:
12
+ import xradio._utils._casacore.casacore_from_casatools as tables
9
13
 
10
14
  from .common import _active_mask, _create_new_image, _object_name, _pointing_center
11
15
  from ..common import _aperture_or_sky, _compute_sky_reference_pixel, _doppler_types
@@ -197,7 +201,7 @@ def _history_from_xds(xds: xr.Dataset, image: str) -> None:
197
201
  def _imageinfo_dict_from_xds(xds: xr.Dataset) -> dict:
198
202
  ii = {}
199
203
  ap_sky = _aperture_or_sky(xds)
200
- ii["image_type"] = (
204
+ ii["imagetype"] = (
201
205
  xds[ap_sky].attrs["image_type"] if "image_type" in xds[ap_sky].attrs else ""
202
206
  )
203
207
  ii["objectname"] = (
@@ -1,8 +1,25 @@
1
- import astropy as ap
1
+ import copy
2
+ import re
3
+ from typing import Union
4
+
5
+ import dask
6
+ import dask.array as da
7
+ import numpy as np
8
+ import xarray as xr
2
9
  from astropy import units as u
3
10
  from astropy.io import fits
4
11
  from astropy.time import Time
5
- from ..common import (
12
+
13
+ from xradio._utils.coord_math import _deg_to_rad
14
+ from xradio._utils.dict_helpers import (
15
+ make_quantity,
16
+ make_frequency_reference_dict,
17
+ make_skycoord_dict,
18
+ make_time_measure_dict,
19
+ )
20
+
21
+ from xradio.measurement_set._utils._utils.stokes_types import stokes_types
22
+ from xradio.image._util.common import (
6
23
  _compute_linear_world_values,
7
24
  _compute_velocity_values,
8
25
  _compute_world_sph_dims,
@@ -15,20 +32,6 @@ from ..common import (
15
32
  _image_type,
16
33
  _l_m_attr_notes,
17
34
  )
18
- from xradio._utils.coord_math import _deg_to_rad
19
- from xradio._utils.dict_helpers import (
20
- make_frequency_reference_dict,
21
- make_quantity,
22
- make_skycoord_dict,
23
- make_time_measure_dict,
24
- )
25
- import copy
26
- import dask
27
- import dask.array as da
28
- import numpy as np
29
- import re
30
- from typing import Union
31
- import xarray as xr
32
35
 
33
36
 
34
37
  def _fits_image_to_xds(
@@ -507,32 +510,7 @@ def _get_time_values(helpers):
507
510
 
508
511
 
509
512
  def _get_pol_values(helpers):
510
- # as mapped in casacore Stokes.h
511
- stokes_map = [
512
- "Undefined",
513
- "I",
514
- "Q",
515
- "U",
516
- "V",
517
- "RR",
518
- "RL",
519
- "LR",
520
- "LL",
521
- "XX",
522
- "XY",
523
- "YX",
524
- "YY",
525
- "RX",
526
- "RY",
527
- "LX",
528
- "LY",
529
- "XR",
530
- "XL",
531
- "YR",
532
- "YL",
533
- "PP",
534
- "PQ",
535
- ]
513
+
536
514
  idx = helpers["ctype"].index("STOKES")
537
515
  if idx >= 0:
538
516
  vals = []
@@ -542,7 +520,13 @@ def _get_pol_values(helpers):
542
520
  stokes_start_idx = crval - cdelt * crpix
543
521
  for i in range(helpers["shape"][idx]):
544
522
  stokes_idx = (stokes_start_idx + i) * cdelt
545
- vals.append(stokes_map[stokes_idx])
523
+ if 0 <= stokes_idx < len(stokes_types):
524
+ # stokes_types provides the index-label mapping from casacore Stokes.h
525
+ vals.append(stokes_types[stokes_idx])
526
+ else:
527
+ raise RuntimeError(
528
+ "Can't find the Stokes type using the FITS header index"
529
+ )
546
530
  return vals
547
531
  else:
548
532
  return ["I"]
@@ -10,7 +10,11 @@ from typing import Union
10
10
 
11
11
  import xarray as xr
12
12
 
13
- from casacore import tables
13
+ try:
14
+ from casacore import tables
15
+ except ImportError:
16
+ import xradio._utils._casacore.casacore_from_casatools as tables
17
+
14
18
  from ._casacore.common import _open_image_ro
15
19
  from ._casacore.xds_from_casacore import (
16
20
  _add_mask,
@@ -21,7 +25,7 @@ from ._casacore.xds_from_casacore import (
21
25
  _get_persistent_block,
22
26
  _get_starts_shapes_slices,
23
27
  _get_transpose_list,
24
- _multibeam_array,
28
+ _get_beam,
25
29
  _read_image_array,
26
30
  )
27
31
  from ._casacore.xds_to_casacore import (
@@ -42,6 +46,8 @@ def _load_casa_image_block(infile: str, block_des: dict, do_sky_coords) -> xr.Da
42
46
  cshape = casa_image.shape()
43
47
  ret = _casa_image_to_xds_coords(image_full_path, False, do_sky_coords)
44
48
  xds = ret["xds"].isel(block_des)
49
+ nchan = ret["xds"].dims["frequency"]
50
+ npol = ret["xds"].dims["polarization"]
45
51
  starts, shapes, slices = _get_starts_shapes_slices(block_des, coords, cshape)
46
52
  dimorder = _get_xds_dim_order(ret["sphr_dims"])
47
53
  transpose_list, new_axes = _get_transpose_list(coords)
@@ -60,13 +66,14 @@ def _load_casa_image_block(infile: str, block_des: dict, do_sky_coords) -> xr.Da
60
66
  # data vars are all caps by convention
61
67
  xds = _add_mask(xds, m.upper(), block, dimorder)
62
68
  xds.attrs = _casa_image_to_xds_attrs(image_full_path)
63
- mb = _multibeam_array(xds, image_full_path, False)
64
- if mb is not None:
65
- selectors = {}
66
- for k in ("time", "frequency", "polarization"):
67
- if k in block_des:
68
- selectors[k] = block_des[k]
69
- xds["BEAM"] = mb.isel(selectors)
69
+ beam = _get_beam(image_full_path, nchan, npol, False)
70
+ if beam is not None:
71
+ selectors = {
72
+ k: block_des[k]
73
+ for k in ("time", "frequency", "polarization")
74
+ if k in block_des
75
+ }
76
+ xds["BEAM"] = beam.isel(selectors)
70
77
  return xds
71
78
 
72
79
 
@@ -97,9 +104,11 @@ def _read_casa_image(
97
104
  # data var names are all caps by convention
98
105
  xds = _add_mask(xds, m.upper(), ary, dimorder)
99
106
  xds.attrs = _casa_image_to_xds_attrs(img_full_path)
100
- mb = _multibeam_array(xds, img_full_path, True)
101
- if mb is not None:
102
- xds["BEAM"] = mb
107
+ beam = _get_beam(
108
+ img_full_path, xds.dims["frequency"], xds.dims["polarization"], True
109
+ )
110
+ if beam is not None:
111
+ xds["BEAM"] = beam
103
112
  # xds = _add_coord_attrs(xds, ret["icoords"], ret["dir_axes"])
104
113
  xds = _dask_arrayize_dv(xds)
105
114
  return xds
xradio/image/image.py CHANGED
@@ -159,7 +159,7 @@ def load_image(infile: str, block_des: dict = {}, do_sky_coords=True) -> xr.Data
159
159
  do_casa = False
160
160
  if do_casa:
161
161
  # comment next line when done debugging
162
- # return _load_casa_image_block(infile, bd, do_sky_coords)
162
+ # return _load_casa_image_block(infile, selection, do_sky_coords)
163
163
  try:
164
164
  return _load_casa_image_block(infile, selection, do_sky_coords)
165
165
  except Exception as e:
@@ -2,7 +2,10 @@ from typing import Tuple
2
2
 
3
3
  import numpy as np
4
4
 
5
- from casacore import tables
5
+ try:
6
+ from casacore import tables
7
+ except ImportError:
8
+ import xradio._utils._casacore.casacore_from_casatools as tables
6
9
  from ....._utils.common import get_pad_value
7
10
 
8
11
 
@@ -5,7 +5,10 @@ import pandas as pd
5
5
  import numpy as np
6
6
  import xarray as xr
7
7
 
8
- from casacore import tables
8
+ try:
9
+ from casacore import tables
10
+ except ImportError:
11
+ import xradio._utils._casacore.casacore_from_casatools as tables
9
12
 
10
13
  from .load import load_col_chunk
11
14
  from .read_main_table import get_partition_ids, redim_id_data_vars, rename_vars
@@ -10,7 +10,11 @@ import pandas as pd
10
10
  import xarray as xr
11
11
 
12
12
  import astropy.units
13
- from casacore import tables
13
+
14
+ try:
15
+ from casacore import tables
16
+ except ImportError:
17
+ import xradio._utils._casacore.casacore_from_casatools as tables
14
18
 
15
19
  from .table_query import open_query, open_table_ro, TableManager
16
20
  from xradio._utils.list_and_array import get_pad_value
@@ -308,6 +312,8 @@ def add_units_measures(
308
312
  ): # Little fix for Meerkat data where the units are a string.
309
313
  cc_units = [cc_units]
310
314
 
315
+ if isinstance(cc_units, np.ndarray):
316
+ cc_units = cc_units.tolist()
311
317
  if not isinstance(cc_units, list) or not cc_units:
312
318
  logger.warning(
313
319
  f"Invalid units found for column/variable {col}: {cc_units}"
@@ -1250,22 +1256,20 @@ def read_col_conversion_numpy(
1250
1256
  # Use casacore to get the shape of a row for this column
1251
1257
  #################################################################################
1252
1258
 
1253
- # getcolshapestring() only works on columns where a row element is an
1254
- # array ie. fails for TIME
1255
- # Assumes the RuntimeError is because the column is a scalar
1256
- try:
1259
+ # getcolshapestring() only works for array-valued columns.
1260
+ # For scalar columns (e.g., EXPOSURE, TIME_CENTROID), it raises a RuntimeError.
1261
+ # So we first check if the column is scalar to avoid that.
1262
+ if tb_tool.isscalarcol(col):
1263
+ extra_dimensions = ()
1264
+ else:
1265
+ # Get the shape string for the first row of the column (e.g., "[4, 2]")
1257
1266
  shape_string = tb_tool.getcolshapestring(col)[0]
1258
- # Convert `shape_string` into a tuple that numpy understands
1267
+
1268
+ # Convert the shape string into a tuple of integers (e.g., (4, 2)) that numpy
1269
+ # understands.
1259
1270
  extra_dimensions = tuple(
1260
- [
1261
- int(idx)
1262
- for idx in shape_string.replace("[", "")
1263
- .replace("]", "")
1264
- .split(", ")
1265
- ]
1271
+ int(dim) for dim in shape_string.strip("[]").split(", ")
1266
1272
  )
1267
- except RuntimeError:
1268
- extra_dimensions = ()
1269
1273
 
1270
1274
  #################################################################################
1271
1275
 
@@ -6,7 +6,10 @@ import numpy as np
6
6
  import xarray as xr
7
7
  import pandas as pd
8
8
 
9
- from casacore import tables
9
+ try:
10
+ from casacore import tables
11
+ except ImportError:
12
+ import xradio._utils._casacore.casacore_from_casatools as tables
10
13
 
11
14
  from .read import (
12
15
  read_flat_col_chunk,
@@ -7,7 +7,10 @@ import numpy as np
7
7
  import pandas as pd
8
8
  import xarray as xr
9
9
 
10
- from casacore import tables
10
+ try:
11
+ from casacore import tables
12
+ except ImportError:
13
+ import xradio._utils._casacore.casacore_from_casatools as tables
11
14
 
12
15
  from .table_query import open_query, open_table_ro
13
16
  from .read import (
@@ -1,7 +1,10 @@
1
1
  from typing import Generator
2
2
  from contextlib import contextmanager
3
3
 
4
- from casacore import tables
4
+ try:
5
+ from casacore import tables
6
+ except ImportError:
7
+ import xradio._utils._casacore.casacore_from_casatools as tables
5
8
 
6
9
 
7
10
  @contextmanager
@@ -17,7 +20,11 @@ def open_table_ro(infile: str) -> Generator[tables.table, None, None]:
17
20
 
18
21
  @contextmanager
19
22
  def open_query(table: tables.table, query: str) -> Generator[tables.table, None, None]:
20
- ttq = tables.taql(query)
23
+
24
+ if hasattr(tables, "taql"):
25
+ ttq = tables.taql(query)
26
+ else:
27
+ ttq = table.taql(query)
21
28
  try:
22
29
  yield ttq
23
30
  finally:
@@ -43,4 +50,7 @@ class TableManager:
43
50
  self.infile, readonly=True, lockoptions={"option": "usernoread"}, ack=False
44
51
  ) as mtable:
45
52
  query = f"select * from $mtable {self.taql_where}"
46
- return tables.taql(query)
53
+ if hasattr(tables, "taql"):
54
+ return tables.taql(query)
55
+ else:
56
+ return mtable.taql(query)
@@ -4,7 +4,10 @@ from typing import Tuple
4
4
  import numpy as np
5
5
  import xarray as xr
6
6
 
7
- from casacore import tables
7
+ try:
8
+ from casacore import tables
9
+ except ImportError:
10
+ import xradio._utils._casacore.casacore_from_casatools as tables
8
11
 
9
12
 
10
13
  def revert_time(datetimes: np.ndarray) -> np.ndarray:
@@ -9,7 +9,10 @@ from ..._utils.xds_helper import flatten_xds, calc_optimal_ms_chunk_shape
9
9
  from .write import write_generic_table, write_main_table_slice
10
10
  from .write import create_table, revert_time
11
11
 
12
- from casacore import tables
12
+ try:
13
+ from casacore import tables
14
+ except ImportError:
15
+ import xradio._utils._casacore.casacore_from_casatools as tables
13
16
 
14
17
 
15
18
  # TODO: this should be consolidated with the equivalent in read_main_table,
@@ -8,9 +8,14 @@ from typing import Dict, Union
8
8
 
9
9
  import numpy as np
10
10
  import xarray as xr
11
+ import traceback
11
12
 
12
13
  import toolviper.utils.logger as logger
13
- from casacore import tables
14
+
15
+ try:
16
+ from casacore import tables
17
+ except ImportError:
18
+ import xradio._utils._casacore.casacore_from_casatools as tables
14
19
 
15
20
  from xradio.measurement_set._utils._msv2.msv4_sub_xdss import (
16
21
  create_pointing_xds,
@@ -648,6 +653,7 @@ def create_data_variables(
648
653
  )
649
654
  except Exception as exc:
650
655
  logger.debug(f"Could not load column {col}, exception: {exc}")
656
+ logger.debug(traceback.format_exc())
651
657
 
652
658
  if ("WEIGHT_SPECTRUM" == col) and (
653
659
  "WEIGHT" in col_names
@@ -1,7 +1,11 @@
1
1
  import numpy as np
2
2
  import xarray as xr
3
3
 
4
- from casacore import tables
4
+ try:
5
+ from casacore import tables
6
+ except ImportError:
7
+ import xradio._utils._casacore.casacore_from_casatools as tables
8
+
5
9
  import toolviper.utils.logger as logger
6
10
 
7
11
  from .subtables import subt_rename_ids
@@ -828,7 +828,7 @@ def create_phased_array_xds(
828
828
  }
829
829
  data_vars["COORDINATE_AXES"].attrs = {
830
830
  "type": "rotation_matrix",
831
- "units": ["undimensioned", "undimensioned", "undimensioned"],
831
+ "units": ["dimensionless", "dimensionless", "dimensionless"],
832
832
  }
833
833
  # Remove the "frame" attribute if it exists, because ELEMENT_OFFSET is
834
834
  # defined in a station-local frame for which no standard name exists
@@ -6,7 +6,10 @@ from typing import Dict, List, Tuple, Union
6
6
  import numpy as np
7
7
  import xarray as xr
8
8
 
9
- from casacore import tables
9
+ try:
10
+ from casacore import tables
11
+ except ImportError:
12
+ import xradio._utils._casacore.casacore_from_casatools as tables
10
13
 
11
14
  from ._tables.table_query import open_table_ro, open_query
12
15
  from ._tables.read import table_exists
@@ -83,8 +83,8 @@ Doppler = Literal["doppler"]
83
83
  RotationMatrix = Literal["rotation_matrix"]
84
84
 
85
85
  # Units of quantities and measures
86
- UnitsUndimensioned = list[
87
- Literal["undimensioned"]
86
+ UnitsDimensionless = list[
87
+ Literal["dimensionless"]
88
88
  ] # name consistent with casacore measures
89
89
  UnitsSeconds = list[Literal["s"]]
90
90
  UnitsHertz = list[Literal["Hz"]]
@@ -2261,7 +2261,7 @@ class PhasedArrayCoordinateAxesArray:
2261
2261
 
2262
2262
  data: Data[tuple[AntennaName, CartesianPosLabelLocal, CartesianPosLabel], float]
2263
2263
 
2264
- units: Attr[UnitsUndimensioned]
2264
+ units: Attr[UnitsDimensionless]
2265
2265
 
2266
2266
  type: Attr[RotationMatrix]
2267
2267
  """ Measure type. Should be ``"rotation_matrix"``."""