xradio 0.0.50__tar.gz → 0.0.52__tar.gz

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 (85) hide show
  1. {xradio-0.0.50/src/xradio.egg-info → xradio-0.0.52}/PKG-INFO +10 -4
  2. xradio-0.0.52/README.md +27 -0
  3. {xradio-0.0.50 → xradio-0.0.52}/pyproject.toml +5 -2
  4. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/dict_helpers.py +24 -0
  5. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/schema.py +2 -2
  6. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_casacore/xds_from_casacore.py +116 -69
  7. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_casacore/xds_to_casacore.py +51 -32
  8. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_fits/xds_from_fits.py +43 -52
  9. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_zarr/common.py +1 -1
  10. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_zarr/xds_from_zarr.py +37 -20
  11. xradio-0.0.52/src/xradio/image/_util/_zarr/xds_to_zarr.py +48 -0
  12. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/casacore.py +6 -3
  13. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/conversion.py +3 -3
  14. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/create_antenna_xds.py +5 -5
  15. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py +11 -3
  16. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +151 -13
  17. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/processing_set_xdt.py +146 -31
  18. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/schema.py +40 -25
  19. {xradio-0.0.50 → xradio-0.0.52/src/xradio.egg-info}/PKG-INFO +10 -4
  20. {xradio-0.0.50 → xradio-0.0.52}/src/xradio.egg-info/requires.txt +1 -1
  21. xradio-0.0.50/README.md +0 -21
  22. xradio-0.0.50/src/xradio/image/_util/_zarr/xds_to_zarr.py +0 -49
  23. {xradio-0.0.50 → xradio-0.0.52}/LICENSE.txt +0 -0
  24. {xradio-0.0.50 → xradio-0.0.52}/MANIFEST.in +0 -0
  25. {xradio-0.0.50 → xradio-0.0.52}/setup.cfg +0 -0
  26. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/__init__.py +0 -0
  27. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/__init__.py +0 -0
  28. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/_casacore/tables.py +0 -0
  29. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/coord_math.py +0 -0
  30. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/list_and_array.py +0 -0
  31. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/zarr/__init__.py +0 -0
  32. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/_utils/zarr/common.py +0 -0
  33. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/__init__.py +0 -0
  34. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/__init__.py +0 -0
  35. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_casacore/__init__.py +0 -0
  36. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_casacore/common.py +0 -0
  37. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/_zarr/zarr_low_level.py +0 -0
  38. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/common.py +0 -0
  39. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/fits.py +0 -0
  40. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/image_factory.py +0 -0
  41. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/_util/zarr.py +0 -0
  42. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/image/image.py +0 -0
  43. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/__init__.py +0 -0
  44. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/__init__.py +0 -0
  45. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/load.py +0 -0
  46. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py +0 -0
  47. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/read.py +0 -0
  48. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py +0 -0
  49. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py +0 -0
  50. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/table_query.py +0 -0
  51. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/write.py +0 -0
  52. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py +0 -0
  53. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/chunks.py +0 -0
  54. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/descr.py +0 -0
  55. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/msv2_msv3.py +0 -0
  56. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py +0 -0
  57. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +0 -0
  58. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/optimised_functions.py +0 -0
  59. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/partition_queries.py +0 -0
  60. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/partitions.py +0 -0
  61. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_msv2/subtables.py +0 -0
  62. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_utils/cds.py +0 -0
  63. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_utils/partition_attrs.py +0 -0
  64. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_utils/stokes_types.py +0 -0
  65. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_utils/xds_helper.py +0 -0
  66. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_zarr/encoding.py +0 -0
  67. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_zarr/read.py +0 -0
  68. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/_zarr/write.py +0 -0
  69. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/msv2.py +0 -0
  70. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/_utils/zarr.py +0 -0
  71. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/convert_msv2_to_processing_set.py +0 -0
  72. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/load_processing_set.py +0 -0
  73. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/measurement_set_xdt.py +0 -0
  74. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/measurement_set/open_processing_set.py +0 -0
  75. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/schema/__init__.py +0 -0
  76. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/schema/bases.py +0 -0
  77. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/schema/check.py +0 -0
  78. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/schema/dataclass.py +0 -0
  79. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/schema/metamodel.py +0 -0
  80. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/schema/typing.py +0 -0
  81. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/sphinx/__init__.py +0 -0
  82. {xradio-0.0.50 → xradio-0.0.52}/src/xradio/sphinx/schema_table.py +0 -0
  83. {xradio-0.0.50 → xradio-0.0.52}/src/xradio.egg-info/SOURCES.txt +0 -0
  84. {xradio-0.0.50 → xradio-0.0.52}/src/xradio.egg-info/dependency_links.txt +0 -0
  85. {xradio-0.0.50 → xradio-0.0.52}/src/xradio.egg-info/top_level.txt +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xradio
3
- Version: 0.0.50
3
+ Version: 0.0.52
4
4
  Summary: Xarray Radio Astronomy Data IO
5
- Author-email: Jan-Willem Steeb <jsteeb@nrao.edu>
5
+ Author-email: Jan-Willem Steeb <jsteeb@nrao.edu>, Federico Montesino Pouzols <pouzols@eso.edu>, Dave Mehringer <dmehring@nrao.edu>, Peter Wortmann <peter.wortmann@skao.int>
6
6
  License: BSD 3-Clause License
7
7
 
8
8
  All works in this repository are copyrighted 2024.
@@ -43,7 +43,7 @@ License-File: LICENSE.txt
43
43
  Requires-Dist: astropy
44
44
  Requires-Dist: dask
45
45
  Requires-Dist: distributed
46
- Requires-Dist: toolviper
46
+ Requires-Dist: toolviper>=0.0.11
47
47
  Requires-Dist: numba>=0.57.0
48
48
  Requires-Dist: numpy
49
49
  Requires-Dist: pytest
@@ -79,7 +79,13 @@ Dynamic: license-file
79
79
  # xradio
80
80
  Xarray Radio Astronomy Data IO is still in development.
81
81
 
82
- [![Python 3.9 3.10 3.11 3.12](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%203.12-blue)](https://www.python.org/downloads/release/python-380/)
82
+ [![Python 3.11 3.12 3.13](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/downloads/release/python-3130/)
83
+ [![Linux Tests](https://github.com/casangi/xradio/actions/workflows/python-testing-linux.yml/badge.svg?branch=main)](https://github.com/casangi/xradio/actions/workflows/python-testing-linux.yml?query=branch%3Amain)
84
+ [![macOS Tests](https://github.com/casangi/xradio/actions/workflows/python-testing-macos.yml/badge.svg?branch=main)](https://github.com/casangi/xradio/actions/workflows/python-testing-macos.yml?query=branch%3Amain)
85
+ [![ipynb Tests](https://github.com/casangi/xradio/actions/workflows/run-ipynb.yml/badge.svg?branch=main)](https://github.com/casangi/xradio/actions/workflows/run-ipynb.yml?query=branch%3Amain)
86
+ [![Coverage](https://codecov.io/gh/casangi/xradio/branch/main/graph/badge.svg)](https://codecov.io/gh/casangi/xradio/branch/main/xradio)
87
+ [![Documentation Status](https://readthedocs.org/projects/xradio/badge/?version=latest)](https://xradio.readthedocs.io)
88
+ [![Version Status](https://img.shields.io/pypi/v/xradio.svg)](https://pypi.python.org/pypi/xradio/)
83
89
 
84
90
  # Installing
85
91
  It is recommended to use the conda environment manager from [miniforge](https://github.com/conda-forge/miniforge) to create a clean, self-contained runtime where XRADIO and all its dependencies can be installed:
@@ -0,0 +1,27 @@
1
+ # xradio
2
+ Xarray Radio Astronomy Data IO is still in development.
3
+
4
+ [![Python 3.11 3.12 3.13](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/downloads/release/python-3130/)
5
+ [![Linux Tests](https://github.com/casangi/xradio/actions/workflows/python-testing-linux.yml/badge.svg?branch=main)](https://github.com/casangi/xradio/actions/workflows/python-testing-linux.yml?query=branch%3Amain)
6
+ [![macOS Tests](https://github.com/casangi/xradio/actions/workflows/python-testing-macos.yml/badge.svg?branch=main)](https://github.com/casangi/xradio/actions/workflows/python-testing-macos.yml?query=branch%3Amain)
7
+ [![ipynb Tests](https://github.com/casangi/xradio/actions/workflows/run-ipynb.yml/badge.svg?branch=main)](https://github.com/casangi/xradio/actions/workflows/run-ipynb.yml?query=branch%3Amain)
8
+ [![Coverage](https://codecov.io/gh/casangi/xradio/branch/main/graph/badge.svg)](https://codecov.io/gh/casangi/xradio/branch/main/xradio)
9
+ [![Documentation Status](https://readthedocs.org/projects/xradio/badge/?version=latest)](https://xradio.readthedocs.io)
10
+ [![Version Status](https://img.shields.io/pypi/v/xradio.svg)](https://pypi.python.org/pypi/xradio/)
11
+
12
+ # Installing
13
+ It is recommended to use the conda environment manager from [miniforge](https://github.com/conda-forge/miniforge) to create a clean, self-contained runtime where XRADIO and all its dependencies can be installed:
14
+ ```sh
15
+ conda create --name xradio python=3.12 --no-default-packages
16
+ conda activate xradio
17
+ ```
18
+ > 📝 On macOS it is required to pre-install `python-casacore` using `conda install -c conda-forge python-casacore`.
19
+
20
+ XRADIO can now be installed using:
21
+ ```sh
22
+ pip install xradio
23
+ ```
24
+ This will also install the minimal dependencies for XRADIO. To install the minimal dependencies and the interactive components (JupyterLab) use:
25
+ ```sh
26
+ pip install "xradio[interactive]"
27
+ ```
@@ -1,9 +1,12 @@
1
1
  [project]
2
2
  name = "xradio"
3
- version = "0.0.50"
3
+ version = "0.0.52"
4
4
  description = " Xarray Radio Astronomy Data IO"
5
5
  authors = [
6
6
  {name = "Jan-Willem Steeb", email="jsteeb@nrao.edu"},
7
+ {name = "Federico Montesino Pouzols", email="pouzols@eso.edu"},
8
+ {name = "Dave Mehringer", email="dmehring@nrao.edu"},
9
+ {name = "Peter Wortmann", email="peter.wortmann@skao.int"}
7
10
  ]
8
11
  license = {file = "LICENSE.txt"}
9
12
  readme = "README.md"
@@ -13,7 +16,7 @@ dependencies = [
13
16
  'astropy',
14
17
  'dask',
15
18
  'distributed',
16
- 'toolviper',
19
+ 'toolviper>=0.0.11',
17
20
  'numba>=0.57.0',
18
21
  'numpy',
19
22
  'pytest',
@@ -43,6 +43,30 @@ def make_time_measure_attrs(units=["s"], scale="utc", time_format="mjd") -> dict
43
43
  return {"units": u, "scale": scale, "format": time_format, "type": "time"}
44
44
 
45
45
 
46
+ def make_time_measure_dict(data, units=["s"], scale="utc", time_format="mjd") -> dict:
47
+ """
48
+ create a time measure dictionary given value and units
49
+ Parameters
50
+ ----------
51
+ value : numeric or array of numerics
52
+ Time value
53
+ units: str
54
+ Time units
55
+ scale: str
56
+ Time scale
57
+ time_format: str
58
+ Time format
59
+ Returns
60
+ -------
61
+ dict
62
+ """
63
+ x = {}
64
+ x["attrs"] = make_time_measure_attrs(units, scale, time_format)
65
+ x["data"] = data
66
+ x["dims"] = []
67
+ return x
68
+
69
+
46
70
  def make_time_coord_attrs(units=["s"], scale="utc", time_format="mjd") -> dict:
47
71
  """
48
72
  create a time measure dictionary given value and units
@@ -190,14 +190,14 @@ casacore_to_msv4_measure_type = {
190
190
  "LSRK": "lsrk",
191
191
  "LSRD": "lsrd",
192
192
  "BARY": "BARY",
193
- "GEO": "GEO",
193
+ "GEO": "gcrs",
194
194
  "TOPO": "TOPO",
195
195
  }, # The frames/observer we are not sure if/how to translate to astropy are uppercase
196
196
  },
197
197
  "position": {
198
198
  "type": "location",
199
199
  "Ref": "frame",
200
- "Ref_map": {"ITRF": "GRS80"},
200
+ "Ref_map": {"ITRF": "ITRS"},
201
201
  },
202
202
  "uvw": {
203
203
  "type": "uvw",
@@ -10,7 +10,7 @@ import numpy as np
10
10
  import xarray as xr
11
11
  from astropy import units as u
12
12
  from casacore import tables
13
- from casacore.images import coordinates
13
+ from casacore.images import coordinates, image as casa_image
14
14
 
15
15
  from .common import (
16
16
  _active_mask,
@@ -32,10 +32,11 @@ from ..common import (
32
32
  from ...._utils._casacore.tables import extract_table_attributes, open_table_ro
33
33
  from xradio._utils.coord_math import _deg_to_rad
34
34
  from xradio._utils.dict_helpers import (
35
- make_quantity,
35
+ _casacore_q_to_xradio_q,
36
36
  make_frequency_reference_dict,
37
+ make_quantity,
37
38
  make_skycoord_dict,
38
- _casacore_q_to_xradio_q,
39
+ make_time_measure_dict,
39
40
  )
40
41
 
41
42
 
@@ -89,19 +90,126 @@ def _add_mask(
89
90
  return xds
90
91
 
91
92
 
93
+ def _casa_image_to_xds_image_attrs(image: casa_image, history: bool = True) -> dict:
94
+ """
95
+ get the image attributes from the casacoreimage object
96
+ """
97
+ meta_dict = image.info()
98
+ coord_dict = copy.deepcopy(meta_dict["coordinates"])
99
+ attrs = {}
100
+ attrs[_image_type] = image.info()["imageinfo"]["imagetype"]
101
+ attrs["units"] = image.unit()
102
+ attrs["telescope"] = {}
103
+ telescope = attrs["telescope"]
104
+ for k in ("observer", "obsdate", "telescope", "telescopeposition"):
105
+ if k.startswith("telescope"):
106
+ if k == "telescope":
107
+ telescope["name"] = coord_dict[k]
108
+ elif k in coord_dict:
109
+ casa_pos = coord_dict[k]
110
+ location = {}
111
+ loc_attrs = {}
112
+ loc_attrs["type"] = "location"
113
+ loc_attrs["frame"] = casa_pos["refer"]
114
+ """
115
+ if casa_pos["refer"] == "ITRF":
116
+ loc_attrs["ellipsoid"] = "GRS80"
117
+ """
118
+ loc_attrs["units"] = [
119
+ casa_pos["m0"]["unit"],
120
+ casa_pos["m1"]["unit"],
121
+ casa_pos["m2"]["unit"],
122
+ ]
123
+ loc_attrs["coordinate_system"] = "geocentric"
124
+ loc_attrs["origin_object_name"] = "earth"
125
+ location["attrs"] = loc_attrs
126
+ location["data"] = [
127
+ casa_pos["m0"]["value"],
128
+ casa_pos["m1"]["value"],
129
+ casa_pos["m2"]["value"],
130
+ ]
131
+ telescope["location"] = location
132
+ """
133
+ del (
134
+ telescope["position"]["refer"],
135
+ telescope["position"]["m0"],
136
+ telescope["position"]["m1"],
137
+ telescope["position"]["m2"],
138
+ )
139
+ """
140
+ elif k == "obsdate":
141
+ obsdate = coord_dict[k]
142
+ """
143
+ o_attrs = {"type": "time"}
144
+ o_attrs["scale"] = coord_dict[k]["refer"]
145
+ myu = coord_dict[k]["m0"]["unit"]
146
+ o_attrs["units"] = myu if isinstance(myu, list) else [myu]
147
+ o_attrs["format"] = _get_time_format(m0["value"], m0["unit"])
148
+ o_date = {}
149
+ o_date["attrs"] = o_attrs
150
+ """
151
+ m0 = obsdate["m0"]
152
+ attrs["obsdate"] = make_time_measure_dict(
153
+ data=m0["value"],
154
+ units=m0["unit"],
155
+ scale=obsdate["refer"],
156
+ time_format=_get_time_format(m0["value"], m0["unit"]),
157
+ )
158
+ else:
159
+ attrs[k] = coord_dict[k] if k in coord_dict else ""
160
+ dir_key = next((k for k in coord_dict if k.startswith("direction")), None)
161
+ if dir_key:
162
+ frame, eqnx = _convert_direction_system(coord_dict[dir_key]["system"], "system")
163
+ else:
164
+ frame = "icrs"
165
+ logger.warning(
166
+ "No direction coordinate found from which "
167
+ "to get pointing center frame. Assuming ICRS"
168
+ )
169
+ # it looks like the pointing center is always in radians in a casa image coord system dict
170
+ # note that in a casa image, the pointing center does not explicitly have a reference frame
171
+ # associated with it.
172
+ # point_center = coord_dict["pointingcenter"]
173
+ attrs[_pointing_center] = make_skycoord_dict(
174
+ coord_dict["pointingcenter"]["value"].tolist(), ["rad", "rad"], frame
175
+ )
176
+ imageinfo = meta_dict["imageinfo"]
177
+ obj = "objectname"
178
+ attrs[_object_name] = imageinfo[obj] if obj in imageinfo else ""
179
+ attrs["user"] = meta_dict["miscinfo"]
180
+ defmask = "Image_defaultmask"
181
+ with open_table_ro(image.name()) as casa_table:
182
+ # the actual mask is a data var and data var names are all caps by convention
183
+ attrs[_active_mask] = (
184
+ casa_table.getkeyword(defmask).upper()
185
+ if defmask in casa_table.keywordnames()
186
+ else None
187
+ )
188
+ attrs["description"] = None
189
+ # if also loading history, put it as another xds in the image attrs
190
+ if history:
191
+ htable = os.sep.join([os.path.abspath(image.name()), "logtable"])
192
+ if os.path.isdir(htable):
193
+ attrs["history"] = read_generic_table(htable)
194
+ else:
195
+ logger.warning(
196
+ f"Unable to find history table {htable}. History will not be included"
197
+ )
198
+ return attrs
199
+
200
+
92
201
  def _add_sky_or_aperture(
93
202
  xds: xr.Dataset,
94
203
  ary: Union[np.ndarray, da.array],
95
204
  dimorder: list,
96
205
  img_full_path: str,
97
206
  has_sph_dims: bool,
207
+ history: bool,
98
208
  ) -> xr.Dataset:
99
209
  xda = xr.DataArray(ary, dims=dimorder).astype(ary.dtype)
100
210
  with _open_image_ro(img_full_path) as casa_image:
101
- image_type = casa_image.info()["imageinfo"]["imagetype"]
102
- unit = casa_image.unit()
103
- xda.attrs[_image_type] = image_type
104
- xda.attrs["units"] = unit
211
+ xda.attrs = _casa_image_to_xds_image_attrs(casa_image, history)
212
+ # xds.attrs = attrs
105
213
  name = "SKY" if has_sph_dims else "APERTURE"
106
214
  xda = xda.rename(name)
107
215
  xds[xda.name] = xda
@@ -143,7 +251,7 @@ def _add_vel_attrs(xds: xr.Dataset, coord_dict: dict) -> xr.Dataset:
143
251
  return xds
144
252
 
145
253
 
146
- def _casa_image_to_xds_attrs(img_full_path: str, history: bool = True) -> dict:
254
+ def _casa_image_to_xds_attrs(img_full_path: str) -> dict:
147
255
  """
148
256
  Get the xds level attribut/es as a python dictionary
149
257
  """
@@ -187,67 +295,6 @@ def _casa_image_to_xds_attrs(img_full_path: str, history: bool = True) -> dict:
187
295
  if j in coord_dir_dict:
188
296
  dir_dict[j] = coord_dir_dict[j]
189
297
  attrs["direction"] = dir_dict
190
- attrs["telescope"] = {}
191
- telescope = attrs["telescope"]
192
- attrs["obsdate"] = {"type": "time"}
193
- obsdate = attrs["obsdate"]
194
- attrs[_pointing_center] = coord_dict["pointingcenter"].copy()
195
- for k in ("observer", "obsdate", "telescope", "telescopeposition"):
196
- if k.startswith("telescope"):
197
- if k == "telescope":
198
- telescope["name"] = coord_dict[k]
199
- elif k in coord_dict:
200
- telescope["position"] = coord_dict[k]
201
- telescope["position"]["ellipsoid"] = telescope["position"]["refer"]
202
- if telescope["position"]["refer"] == "ITRF":
203
- telescope["position"]["ellipsoid"] = "GRS80"
204
- telescope["position"]["units"] = [
205
- telescope["position"]["m0"]["unit"],
206
- telescope["position"]["m1"]["unit"],
207
- telescope["position"]["m2"]["unit"],
208
- ]
209
- telescope["position"]["value"] = [
210
- telescope["position"]["m0"]["value"],
211
- telescope["position"]["m1"]["value"],
212
- telescope["position"]["m2"]["value"],
213
- ]
214
- del (
215
- telescope["position"]["refer"],
216
- telescope["position"]["m0"],
217
- telescope["position"]["m1"],
218
- telescope["position"]["m2"],
219
- )
220
- elif k == "obsdate":
221
- obsdate["scale"] = coord_dict[k]["refer"]
222
- myu = coord_dict[k]["m0"]["unit"]
223
- obsdate["units"] = myu if isinstance(myu, list) else [myu]
224
- obsdate["value"] = coord_dict[k]["m0"]["value"]
225
- obsdate["format"] = _get_time_format(obsdate["value"], obsdate["units"])
226
- obsdate["type"] = "time"
227
- else:
228
- attrs[k] = coord_dict[k] if k in coord_dict else ""
229
- imageinfo = meta_dict["imageinfo"]
230
- obj = "objectname"
231
- attrs[_object_name] = imageinfo[obj] if obj in imageinfo else ""
232
- attrs["user"] = meta_dict["miscinfo"]
233
- defmask = "Image_defaultmask"
234
- with open_table_ro(img_full_path) as casa_table:
235
- # the actual mask is a data var and data var names are all caps by convention
236
- attrs[_active_mask] = (
237
- casa_table.getkeyword(defmask).upper()
238
- if defmask in casa_table.keywordnames()
239
- else None
240
- )
241
- attrs["description"] = None
242
- # if also loading history, put it as another xds in the attrs
243
- if history:
244
- htable = os.sep.join([img_full_path, "logtable"])
245
- if os.path.isdir(htable):
246
- attrs["history"] = read_generic_table(htable)
247
- else:
248
- logger.warning(
249
- f"Unable to find history table {htable}. History will not be included"
250
- )
251
298
  return copy.deepcopy(attrs)
252
299
 
253
300
 
@@ -19,12 +19,16 @@ def _compute_direction_dict(xds: xr.Dataset) -> dict:
19
19
  """
20
20
  direction = {}
21
21
  xds_dir = xds.attrs["direction"]
22
+ direction["_axes_sizes"] = np.array(
23
+ [xds.sizes[dim] for dim in ("l", "m")], dtype=np.int32
24
+ )
25
+ direction["_image_axes"] = np.array([2, 3], dtype=np.int32)
22
26
  direction["system"] = xds_dir["reference"]["attrs"]["equinox"].upper()
23
27
  if direction["system"] == "J2000.0":
24
28
  direction["system"] = "J2000"
25
29
  direction["projection"] = xds_dir["projection"]
26
30
  direction["projection_parameters"] = xds_dir["projection_parameters"]
27
- direction["units"] = np.array(xds_dir["reference"]["attrs"]["units"], dtype="<U16")
31
+ direction["units"] = xds_dir["reference"]["attrs"]["units"]
28
32
  direction["crval"] = np.array(xds_dir["reference"]["data"])
29
33
  direction["cdelt"] = np.array((xds.l[1] - xds.l[0], xds.m[1] - xds.m[0]))
30
34
  direction["crpix"] = _compute_sky_reference_pixel(xds)
@@ -34,9 +38,9 @@ def _compute_direction_dict(xds: xr.Dataset) -> dict:
34
38
  for s in ["longpole", "latpole"]:
35
39
  m = "lonpole" if s == "longpole" else s
36
40
  # 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
41
+ direction[s] = float(
42
+ Angle(str(xds_dir[m]["data"]) + xds_dir[m]["attrs"]["units"][0]).deg
43
+ )
40
44
  return direction
41
45
 
42
46
 
@@ -69,6 +73,8 @@ def _compute_spectral_dict(xds: xr.Dataset) -> dict:
69
73
  for a CASA image coordinate system
70
74
  """
71
75
  spec = {}
76
+ spec["_axes_sizes"] = np.array([xds.sizes["frequency"]], dtype=np.int32)
77
+ spec["_image_axes"] = np.array([0], dtype=np.int32)
72
78
  spec["formatUnit"] = ""
73
79
  spec["name"] = "Frequency"
74
80
  # spec["nativeType"] = _native_types.index(xds.frequency.attrs["native_type"])
@@ -76,7 +82,7 @@ def _compute_spectral_dict(xds: xr.Dataset) -> dict:
76
82
  spec["nativeType"] = 0
77
83
  spec["restfreq"] = xds.frequency.attrs["rest_frequency"]["data"]
78
84
  # spec["restfreqs"] = copy.deepcopy(xds.frequency.attrs["restfreqs"]["value"])
79
- spec["restfreqs"] = [spec["restfreq"]]
85
+ spec["restfreqs"] = np.array([spec["restfreq"]])
80
86
  spec["system"] = xds.frequency.attrs["reference_value"]["attrs"]["observer"].upper()
81
87
  u = xds.frequency.attrs["reference_value"]["attrs"]["units"]
82
88
  spec["unit"] = u if isinstance(u, str) else u[0]
@@ -88,53 +94,65 @@ def _compute_spectral_dict(xds: xr.Dataset) -> dict:
88
94
  wcs = {}
89
95
  wcs["ctype"] = "FREQ"
90
96
  wcs["pc"] = 1.0
91
- wcs["crval"] = xds.frequency.attrs["reference_value"]["data"]
92
- wcs["cdelt"] = xds.frequency.values[1] - xds.frequency.values[0]
93
- wcs["crpix"] = (wcs["crval"] - xds.frequency.values[0]) / wcs["cdelt"]
97
+ wcs["crval"] = float(xds.frequency.attrs["reference_value"]["data"])
98
+ wcs["cdelt"] = float(xds.frequency.values[1] - xds.frequency.values[0])
99
+ wcs["crpix"] = float((wcs["crval"] - xds.frequency.values[0]) / wcs["cdelt"])
94
100
  spec["wcs"] = wcs
95
101
  return spec
96
102
 
97
103
 
98
104
  def _coord_dict_from_xds(xds: xr.Dataset) -> dict:
99
105
  coord = {}
100
- coord["telescope"] = xds.attrs["telescope"]["name"]
101
- coord["observer"] = xds.attrs["observer"]
106
+ sky_ap = "SKY" if "SKY" in xds.data_vars else "APERTURE"
107
+ if "telescope" in xds[sky_ap].attrs:
108
+ tel = xds[sky_ap].attrs["telescope"]
109
+ if "name" in tel:
110
+ coord["telescope"] = xds[sky_ap].attrs["telescope"]["name"]
111
+ if "location" in tel:
112
+ xds_telloc = tel["location"]
113
+ telloc = {}
114
+ telloc["refer"] = xds_telloc["attrs"]["frame"]
115
+ if telloc["refer"] == "GRS80":
116
+ telloc["refer"] = "ITRF"
117
+ for i in range(3):
118
+ telloc[f"m{i}"] = {
119
+ "unit": xds_telloc["attrs"]["units"][i],
120
+ "value": xds_telloc["data"][i],
121
+ }
122
+ telloc["type"] = "position"
123
+ coord["telescopeposition"] = telloc
124
+ if "observer" in xds[sky_ap].attrs:
125
+ coord["observer"] = xds[sky_ap].attrs["observer"]
102
126
  obsdate = {}
103
127
  obsdate["refer"] = xds.coords["time"].attrs["scale"]
104
128
  obsdate["type"] = "epoch"
105
129
  obsdate["m0"] = {}
106
130
  obsdate["m0"]["unit"] = xds.coords["time"].attrs["units"][0]
107
- obsdate["m0"]["value"] = xds.coords["time"].values[0]
131
+ obsdate["m0"]["value"] = float(xds.coords["time"].values[0])
108
132
  coord["obsdate"] = obsdate
109
- coord["pointingcenter"] = xds.attrs[_pointing_center].copy()
110
- if "position" in xds.attrs["telescope"]:
111
- telpos = {}
112
- telpos["refer"] = xds.attrs["telescope"]["position"]["ellipsoid"]
113
- if xds.attrs["telescope"]["position"]["ellipsoid"] == "GRS80":
114
- telpos["refer"] = "ITRF"
115
- for i in range(3):
116
- telpos[f"m{i}"] = {
117
- "unit": xds.attrs["telescope"]["position"]["units"][i],
118
- "value": xds.attrs["telescope"]["position"]["value"][i],
119
- }
120
- telpos["type"] = "position"
121
- coord["telescopeposition"] = telpos
133
+ if _pointing_center in xds[sky_ap].attrs:
134
+ coord["pointingcenter"] = {
135
+ "initial": True,
136
+ "value": xds[sky_ap].attrs[_pointing_center]["data"],
137
+ }
122
138
  if "l" in xds.coords:
123
139
  coord["direction0"] = _compute_direction_dict(xds)
124
140
  else:
125
141
  coord["linear0"] = _compute_linear_dict(xds)
126
142
  coord["stokes1"] = {
127
- "axes": np.array(["Stokes"], dtype="<U16"),
143
+ "_axes_sizes": np.array([xds.sizes["polarization"]], dtype=np.int32),
144
+ "_image_axes": np.array([1], dtype=np.int32),
145
+ "axes": ["Stokes"],
128
146
  "cdelt": np.array([1.0]),
129
147
  "crpix": np.array([0.0]),
130
148
  "crval": np.array([1.0]),
131
149
  "pc": np.array([[1.0]]),
132
- "stokes": np.array(xds.polarization.values, dtype="<U16"),
150
+ "stokes": xds.polarization.values.tolist(),
133
151
  }
134
152
  coord["spectral2"] = _compute_spectral_dict(xds)
135
- coord["pixelmap0"] = np.array([0, 1])
136
- coord["pixelmap1"] = np.array([2])
137
- coord["pixelmap2"] = np.array([3])
153
+ coord["pixelmap0"] = np.array([0, 1], dtype=np.int32)
154
+ coord["pixelmap1"] = np.array([2], dtype=np.int32)
155
+ coord["pixelmap2"] = np.array([3], dtype=np.int32)
138
156
  coord["pixelreplace0"] = np.array([0.0, 0.0])
139
157
  coord["pixelreplace1"] = np.array([0.0])
140
158
  coord["pixelreplace2"] = np.array([0.0])
@@ -144,7 +162,6 @@ def _coord_dict_from_xds(xds: xr.Dataset) -> dict:
144
162
  # this probbably needs some verification
145
163
  coord["worldreplace0"] = [0.0, 0.0]
146
164
  coord["worldreplace1"] = np.array(coord["stokes1"]["crval"])
147
- # print("spectral", coord["spectral2"])
148
165
  coord["worldreplace2"] = np.array(coord["spectral2"]["wcs"]["crval"])
149
166
  return coord
150
167
 
@@ -181,7 +198,7 @@ def _imageinfo_dict_from_xds(xds: xr.Dataset) -> dict:
181
198
  ii["image_type"] = (
182
199
  xds[ap_sky].attrs["image_type"] if "image_type" in xds[ap_sky].attrs else ""
183
200
  )
184
- ii["objectname"] = xds.attrs[_object_name]
201
+ ii["objectname"] = xds[ap_sky].attrs[_object_name]
185
202
  if "BEAM" in xds.data_vars:
186
203
  # multi beam
187
204
  pp = {}
@@ -231,7 +248,9 @@ def _write_casa_data(xds: xr.Dataset, image_full_path: str) -> None:
231
248
  else ("frequency", "polarization", "v", "u")
232
249
  )
233
250
  casa_image_shape = xds[sky_ap].isel(time=0).transpose(*trans_coords).shape[::-1]
234
- active_mask = xds.attrs["active_mask"] if _active_mask in xds.attrs else ""
251
+ active_mask = (
252
+ xds[sky_ap].attrs["active_mask"] if _active_mask in xds[sky_ap].attrs else ""
253
+ )
235
254
  masks = []
236
255
  masks_rec = {}
237
256
  mask_rec = {