xradio 0.0.41__tar.gz → 0.0.42__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 (89) hide show
  1. {xradio-0.0.41/src/xradio.egg-info → xradio-0.0.42}/PKG-INFO +9 -6
  2. xradio-0.0.42/README.md +21 -0
  3. {xradio-0.0.41 → xradio-0.0.42}/pyproject.toml +1 -1
  4. xradio-0.0.42/src/xradio/_utils/coord_math.py +100 -0
  5. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/_utils/list_and_array.py +49 -4
  6. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/_utils/schema.py +36 -16
  7. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_casacore/xds_from_casacore.py +5 -5
  8. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_casacore/xds_to_casacore.py +12 -11
  9. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_fits/xds_from_fits.py +18 -17
  10. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_zarr/zarr_low_level.py +29 -12
  11. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/common.py +1 -1
  12. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/image_factory.py +1 -1
  13. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/__init__.py +7 -4
  14. xradio-0.0.42/src/xradio/measurement_set/_utils/__init__.py +5 -0
  15. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/load_main_table.py +1 -1
  16. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/read.py +1 -1
  17. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/conversion.py +78 -35
  18. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/create_antenna_xds.py +62 -37
  19. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/create_field_and_source_xds.py +109 -22
  20. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/msv4_sub_xdss.py +47 -13
  21. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/_utils/xds_helper.py +1 -1
  22. xradio-0.0.41/src/xradio/correlated_data/_utils/ms.py → xradio-0.0.42/src/xradio/measurement_set/_utils/msv2.py +4 -4
  23. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/convert_msv2_to_processing_set.py +2 -2
  24. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/load_processing_set.py +5 -5
  25. xradio-0.0.42/src/xradio/measurement_set/measurement_set_xds.py +83 -0
  26. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/open_processing_set.py +9 -16
  27. xradio-0.0.42/src/xradio/measurement_set/processing_set.py +777 -0
  28. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/schema.py +1101 -610
  29. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/schema/check.py +42 -22
  30. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/schema/dataclass.py +56 -6
  31. xradio-0.0.42/src/xradio/sphinx/__init__.py +12 -0
  32. xradio-0.0.42/src/xradio/sphinx/schema_table.py +351 -0
  33. {xradio-0.0.41 → xradio-0.0.42/src/xradio.egg-info}/PKG-INFO +9 -6
  34. xradio-0.0.42/src/xradio.egg-info/SOURCES.txt +80 -0
  35. xradio-0.0.41/README.md +0 -18
  36. xradio-0.0.41/src/xradio/_utils/common.py +0 -101
  37. xradio-0.0.41/src/xradio/correlated_data/_utils/__init__.py +0 -5
  38. xradio-0.0.41/src/xradio/correlated_data/correlated_xds.py +0 -13
  39. xradio-0.0.41/src/xradio/correlated_data/processing_set.py +0 -301
  40. xradio-0.0.41/src/xradio/correlated_data/test__processing_set.py +0 -74
  41. xradio-0.0.41/src/xradio.egg-info/SOURCES.txt +0 -79
  42. {xradio-0.0.41 → xradio-0.0.42}/LICENSE.txt +0 -0
  43. {xradio-0.0.41 → xradio-0.0.42}/MANIFEST.in +0 -0
  44. {xradio-0.0.41 → xradio-0.0.42}/setup.cfg +0 -0
  45. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/__init__.py +0 -0
  46. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/_utils/__init__.py +0 -0
  47. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/_utils/_casacore/tables.py +0 -0
  48. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/_utils/zarr/__init__.py +0 -0
  49. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/_utils/zarr/common.py +0 -0
  50. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/__init__.py +0 -0
  51. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/__init__.py +0 -0
  52. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_casacore/__init__.py +0 -0
  53. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_casacore/common.py +0 -0
  54. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_zarr/common.py +0 -0
  55. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_zarr/xds_from_zarr.py +0 -0
  56. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/_zarr/xds_to_zarr.py +0 -0
  57. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/casacore.py +0 -0
  58. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/fits.py +0 -0
  59. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/_util/zarr.py +0 -0
  60. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/image/image.py +0 -0
  61. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/load.py +0 -0
  62. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/read_main_table.py +0 -0
  63. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/read_subtables.py +0 -0
  64. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/table_query.py +0 -0
  65. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/write.py +0 -0
  66. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/_tables/write_exp_api.py +0 -0
  67. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/chunks.py +0 -0
  68. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/descr.py +0 -0
  69. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/msv2_msv3.py +0 -0
  70. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/msv2_to_msv4_meta.py +0 -0
  71. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/msv4_info_dicts.py +0 -0
  72. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/optimised_functions.py +0 -0
  73. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/partition_queries.py +0 -0
  74. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/partitions.py +0 -0
  75. {xradio-0.0.41/src/xradio/correlated_data/_utils/_ms → xradio-0.0.42/src/xradio/measurement_set/_utils/_msv2}/subtables.py +0 -0
  76. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/_utils/cds.py +0 -0
  77. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/_utils/partition_attrs.py +0 -0
  78. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/_utils/stokes_types.py +0 -0
  79. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/_zarr/encoding.py +0 -0
  80. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/_zarr/read.py +0 -0
  81. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/_zarr/write.py +0 -0
  82. {xradio-0.0.41/src/xradio/correlated_data → xradio-0.0.42/src/xradio/measurement_set}/_utils/zarr.py +0 -0
  83. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/schema/__init__.py +0 -0
  84. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/schema/bases.py +0 -0
  85. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/schema/metamodel.py +0 -0
  86. {xradio-0.0.41 → xradio-0.0.42}/src/xradio/schema/typing.py +0 -0
  87. {xradio-0.0.41 → xradio-0.0.42}/src/xradio.egg-info/dependency_links.txt +0 -0
  88. {xradio-0.0.41 → xradio-0.0.42}/src/xradio.egg-info/requires.txt +0 -0
  89. {xradio-0.0.41 → xradio-0.0.42}/src/xradio.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xradio
3
- Version: 0.0.41
3
+ Version: 0.0.42
4
4
  Summary: Xarray Radio Astronomy Data IO
5
5
  Author-email: Jan-Willem Steeb <jsteeb@nrao.edu>
6
6
  License: BSD 3-Clause License
@@ -78,18 +78,21 @@ Requires-Dist: pandoc; extra == "docs"
78
78
  # xradio
79
79
  Xarray Radio Astronomy Data IO is still in development.
80
80
 
81
- [![Python 3.9 3.10 3.11](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11-blue)](https://www.python.org/downloads/release/python-380/)
81
+ [![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
82
 
83
83
  # Installing
84
- It is recommended to use the [conda](https://docs.conda.io/projects/conda/en/latest/) environment manager to create a clean, self-contained runtime where xradio and all its dependencies can be installed:
84
+ 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:
85
85
  ```sh
86
- conda create --name xradio python=3.11 --no-default-packages
86
+ conda create --name xradio python=3.12 --no-default-packages
87
87
  conda activate xradio
88
-
89
88
  ```
90
89
  > 📝 On macOS it is required to pre-install `python-casacore` using `conda install -c conda-forge python-casacore`.
91
90
 
92
- Making xradio available for download from conda-forge directly is pending, so until then the current recommendation is to sully that pristine environment by calling pip [from within conda](https://www.anaconda.com/blog/using-pip-in-a-conda-environment), like this:
91
+ XRADIO can now be installed using:
93
92
  ```sh
94
93
  pip install xradio
95
94
  ```
95
+ This will also install the minimal dependencies for XRADIO. To install the minimal dependencies and the interactive components (JupyterLab) use:
96
+ ```sh
97
+ pip install "xradio[interactive]"
98
+ ```
@@ -0,0 +1,21 @@
1
+ # xradio
2
+ Xarray Radio Astronomy Data IO is still in development.
3
+
4
+ [![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/)
5
+
6
+ # Installing
7
+ 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:
8
+ ```sh
9
+ conda create --name xradio python=3.12 --no-default-packages
10
+ conda activate xradio
11
+ ```
12
+ > 📝 On macOS it is required to pre-install `python-casacore` using `conda install -c conda-forge python-casacore`.
13
+
14
+ XRADIO can now be installed using:
15
+ ```sh
16
+ pip install xradio
17
+ ```
18
+ This will also install the minimal dependencies for XRADIO. To install the minimal dependencies and the interactive components (JupyterLab) use:
19
+ ```sh
20
+ pip install "xradio[interactive]"
21
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xradio"
3
- version = "0.0.41"
3
+ version = "0.0.42"
4
4
  description = " Xarray Radio Astronomy Data IO"
5
5
  authors = [
6
6
  {name = "Jan-Willem Steeb", email="jsteeb@nrao.edu"},
@@ -0,0 +1,100 @@
1
+ import numpy as np
2
+
3
+ _deg_to_rad = np.pi / 180
4
+
5
+
6
+ def haversine(ra1, dec1, ra2, dec2):
7
+ """
8
+ Calculate the great circle distance between two points
9
+ on the celestial sphere specified in radians.
10
+ """
11
+ # Haversine formula
12
+ d_ra = ra2 - ra1
13
+ d_dec = dec2 - dec1
14
+ a = np.sin(d_dec / 2) ** 2 + np.cos(dec1) * np.cos(dec2) * np.sin(d_ra / 2) ** 2
15
+ c = 2 * np.arcsin(np.sqrt(a))
16
+ return c
17
+
18
+
19
+ def add_position_offsets(dv_1, dv_2):
20
+ # Fun with angles: We are adding angles together. We need to make sure that the results are between -pi and pi.
21
+ new_pos = dv_1 + dv_2
22
+
23
+ new_pos = wrap_to_pi(new_pos)
24
+
25
+ # while np.any(new_pos[:, 0] > np.pi) or np.any(new_pos[:, 0] < -np.pi):
26
+ # new_pos[:, 0] = np.where(
27
+ # new_pos[:, 0] > np.pi, new_pos[:, 0] - 2 * np.pi, new_pos[:, 0]
28
+ # )
29
+ # new_pos[:, 0] = np.where(
30
+ # new_pos[:, 0] < -np.pi, new_pos[:, 0] + 2 * np.pi, new_pos[:, 0]
31
+ # )
32
+
33
+ # while np.any(new_pos[:, 1] > np.pi / 2) or np.any(new_pos[:, 1] < -np.pi / 2):
34
+ # new_pos[:, 1] = np.where(
35
+ # new_pos[:, 1] > np.pi / 2, new_pos[:, 1] - np.pi, new_pos[:, 1]
36
+ # )
37
+ # new_pos[:, 1] = np.where(
38
+ # new_pos[:, 1] < -np.pi / 2, new_pos[:, 1] + np.pi, new_pos[:, 1]
39
+ # )
40
+
41
+ return new_pos
42
+
43
+
44
+ def wrap_to_pi(angles):
45
+ """
46
+ Wraps an array of angles in radians to the range (-π, π].
47
+
48
+ Parameters:
49
+ -----------
50
+ angles : array_like
51
+ Input array of angles in radians.
52
+
53
+ Returns:
54
+ --------
55
+ array_like
56
+ The input angles wrapped to the range (-π, π].
57
+
58
+ Examples:
59
+ ---------
60
+ >>> wrap_to_pi(np.array([0, np.pi, -np.pi, 3*np.pi, -3*np.pi]))
61
+ array([ 0. , 3.14159265, -3.14159265, 3.14159265, -3.14159265])
62
+ """
63
+ return (angles + np.pi) % (2 * np.pi) - np.pi
64
+
65
+
66
+ def wrap_to_pi(angles):
67
+ return (angles + np.pi) % (2 * np.pi) - np.pi
68
+
69
+
70
+ def convert_to_si_units(xds):
71
+ for data_var in xds.data_vars:
72
+ if "units" in xds[data_var].attrs:
73
+ for u_i, u in enumerate(xds[data_var].attrs["units"]):
74
+ if u == "km":
75
+ xds[data_var][..., u_i] = xds[data_var][..., u_i] * 1e3
76
+ xds[data_var].attrs["units"][u_i] = "m"
77
+ if u == "km/s":
78
+ xds[data_var][..., u_i] = xds[data_var][..., u_i] * 1e3
79
+ xds[data_var].attrs["units"][u_i] = "m/s"
80
+ if u == "deg":
81
+ xds[data_var][..., u_i] = xds[data_var][..., u_i] * np.pi / 180
82
+ xds[data_var].attrs["units"][u_i] = "rad"
83
+ if u == "Au" or u == "AU":
84
+ xds[data_var][..., u_i] = xds[data_var][..., u_i] * 149597870700
85
+ xds[data_var].attrs["units"][u_i] = "m"
86
+ if u == "Au/d" or u == "AU/d":
87
+ xds[data_var][..., u_i] = (
88
+ xds[data_var][..., u_i] * 149597870700 / 86400
89
+ )
90
+ xds[data_var].attrs["units"][u_i] = "m/s"
91
+ if u == "arcsec":
92
+ xds[data_var][..., u_i] = xds[data_var][..., u_i] * np.pi / 648000
93
+ xds[data_var].attrs["units"][u_i] = "rad"
94
+ if u == "hPa":
95
+ xds[data_var][..., u_i] = xds[data_var][..., u_i] * 100.0
96
+ xds[data_var].attrs["units"][u_i] = "Pa"
97
+ if u == "m-2":
98
+ # IONOS_ELECTRON sometimes has "m-2" instead of "/m^2"
99
+ xds[data_var].attrs["units"][u_i] = "/m^2"
100
+ return xds
@@ -2,6 +2,55 @@
2
2
 
3
3
  import numpy as np
4
4
  import xarray as xr
5
+ import pandas as pd
6
+
7
+
8
+ def cast_to_str(x):
9
+ if isinstance(x, list):
10
+ return x[0]
11
+ else:
12
+ return x
13
+
14
+
15
+ def get_pad_value(col_dtype: np.dtype) -> object:
16
+ """
17
+ Produce a padding/missing/nan value appropriate for a casacore data column
18
+ (for when we need to pad data vars coming from columns with rows of
19
+ variable size array values)
20
+
21
+ Parameters
22
+ ----------
23
+ col_dtype : dtype
24
+ dtype of data being loaded from a table column
25
+
26
+ Returns
27
+ -------
28
+ object
29
+ pad value ("missing" / "fill") for the type given
30
+ """
31
+ # Fill values for missing/NaN data in integer variables, based on usual
32
+ # numpy fill values. See https://github.com/numpy/numpy/issues/21166,
33
+ # https://github.com/casangi/xradio/issues/219, https://github.com/casangi/xradio/pull/177
34
+ fill_value_int32 = np.int32(-2147483648)
35
+ fill_value_int64 = np.int64(-9223372036854775808)
36
+
37
+ if col_dtype == np.int32:
38
+ return fill_value_int32
39
+ elif col_dtype == np.int64 or col_dtype == "int":
40
+ return fill_value_int64
41
+ elif np.issubdtype(col_dtype, np.floating):
42
+ return np.nan
43
+ elif np.issubdtype(col_dtype, np.complexfloating):
44
+ return complex(np.nan, np.nan)
45
+ elif np.issubdtype(col_dtype, np.bool_):
46
+ return False
47
+ elif np.issubdtype(col_dtype, str):
48
+ return ""
49
+ else:
50
+ raise RuntimeError(
51
+ "Padding / missing value not defined for the type requested: "
52
+ f"{col_dtype} (of type: {type(col_dtype)})"
53
+ )
5
54
 
6
55
 
7
56
  def to_list(x):
@@ -45,10 +94,6 @@ def check_if_consistent(array: np.ndarray, array_name: str) -> np.ndarray:
45
94
  return array_unique[0]
46
95
 
47
96
 
48
- import numpy as np
49
- import pandas as pd
50
-
51
-
52
97
  def unique_1d(array: np.ndarray) -> np.ndarray:
53
98
  """
54
99
  Optimised version of np.unique for 1D arrays.
@@ -93,7 +93,7 @@ def convert_generic_xds_to_xradio_schema(
93
93
 
94
94
 
95
95
  def column_description_casacore_to_msv4_measure(
96
- casacore_column_description, ref_code=None, time_format="UNIX"
96
+ casacore_column_description, ref_code=None, time_format="unix"
97
97
  ):
98
98
  import numpy as np
99
99
 
@@ -136,9 +136,14 @@ def column_description_casacore_to_msv4_measure(
136
136
  casa_ref = msv4_measure_conversion["Ref_map"][casa_ref]
137
137
  else:
138
138
  logger.debug(
139
- f"Unknown reference frame for {measinfo['type']} "
140
- f"measure, using verbatim: {casa_ref}"
139
+ f"No translation defined for casacore reference frame ({measinfo['type']} "
140
+ f"measure), using verbatim: {casa_ref}"
141
141
  )
142
+ if measinfo["type"] == "direction" and casa_ref == "B1950_VLA":
143
+ raise RuntimeError(
144
+ f"The direction reference frame {casa_ref} is not supported. "
145
+ "Please use CASA to convert the frame to supported frames like J2000 or ICRS."
146
+ )
142
147
 
143
148
  msv4_measure[msv4_measure_conversion["Ref"]] = casa_ref
144
149
 
@@ -158,30 +163,45 @@ casacore_to_msv4_measure_type = {
158
163
  "quanta": {
159
164
  "type": "quantity",
160
165
  },
161
- "direction": {"type": "sky_coord", "Ref": "frame", "Ref_map": {"J2000": "fk5"}},
162
- "epoch": {"type": "time", "Ref": "scale", "Ref_map": {"UTC": "utc"}},
166
+ "direction": {
167
+ "type": "sky_coord",
168
+ "Ref": "frame",
169
+ "Ref_map": {
170
+ "AZELGEO": "altaz",
171
+ "ICRS": "icrs",
172
+ "J2000": "fk5",
173
+ },
174
+ },
175
+ "epoch": {
176
+ "type": "time",
177
+ "Ref": "scale",
178
+ "Ref_map": {
179
+ "UTC": "utc",
180
+ "TAI": "tai",
181
+ },
182
+ },
163
183
  "frequency": {
164
184
  "type": "spectral_coord",
165
- "Ref": "frame",
185
+ "Ref": "observer",
166
186
  "Ref_map": {
167
187
  "REST": "REST",
168
- "LSRK": "LSRK",
169
- "LSRD": "LSRD",
188
+ "LSRK": "lsrk",
189
+ "LSRD": "lsrd",
170
190
  "BARY": "BARY",
171
191
  "GEO": "GEO",
172
192
  "TOPO": "TOPO",
173
- "GALACTO": "GALACTO",
174
- "LGROUP": "LGROUP",
175
- "CMB": "CMB",
176
- "Undefined": "Undefined",
177
- },
193
+ }, # The frames/observer we are not sure if/how to translate to astropy are uppercase
178
194
  },
179
195
  "position": {
180
- "type": "earth_location",
181
- "Ref": "ellipsoid",
196
+ "type": "location",
197
+ "Ref": "frame",
182
198
  "Ref_map": {"ITRF": "GRS80"},
183
199
  },
184
- "uvw": {"type": "uvw", "Ref": "frame", "Ref_map": {"ITRF": "GRS80"}},
200
+ "uvw": {
201
+ "type": "uvw",
202
+ "Ref": "frame",
203
+ "Ref_map": {"J2000": "fk5", "APP": "APP"},
204
+ },
185
205
  "radialvelocity": {"type": "quantity"},
186
206
  }
187
207
 
@@ -30,7 +30,7 @@ from ..common import (
30
30
  _l_m_attr_notes,
31
31
  )
32
32
  from ...._utils._casacore.tables import extract_table_attributes, open_table_ro
33
- from ...._utils.common import _deg_to_rad
33
+ from xradio._utils.coord_math import _deg_to_rad
34
34
 
35
35
  """
36
36
  def _add_coord_attrs(xds: xr.Dataset, icoords: dict, dir_axes: list) -> xr.Dataset:
@@ -204,7 +204,7 @@ def _casa_image_to_xds_attrs(img_full_path: str, history: bool = True) -> dict:
204
204
  if k.startswith("telescope"):
205
205
  if k == "telescope":
206
206
  telescope["name"] = coord_dict[k]
207
- else:
207
+ elif k in coord_dict:
208
208
  telescope["position"] = coord_dict[k]
209
209
  telescope["position"]["ellipsoid"] = telescope["position"]["refer"]
210
210
  if telescope["position"]["refer"] == "ITRF":
@@ -362,7 +362,7 @@ def _convert_direction_system(
362
362
  'This corresponds to FK5(equinox="J2000") in astropy. '
363
363
  "Metadata will be written appropriately"
364
364
  )
365
- return ("FK5", "J2000")
365
+ return ("FK5", "J2000.0")
366
366
  elif casa_system == "B1950":
367
367
  if verbose:
368
368
  logger.info(
@@ -370,9 +370,9 @@ def _convert_direction_system(
370
370
  'This corresponds to FK4(equinox="B1950") in astropy. '
371
371
  "Metadata will be written appropriately"
372
372
  )
373
- return ("FK4", "B1950")
373
+ return ("FK4", "B1950.0")
374
374
  elif casa_system in ("GALACTIC", "ICRS"):
375
- return (casa_system, None)
375
+ return (casa_system.lower(), None)
376
376
  else:
377
377
  raise Exception(
378
378
  f"astropy does not support frame {casa_system} and this "
@@ -100,17 +100,18 @@ def _coord_dict_from_xds(xds: xr.Dataset) -> dict:
100
100
  obsdate["m0"]["value"] = xds.coords["time"].values[0]
101
101
  coord["obsdate"] = obsdate
102
102
  coord["pointingcenter"] = xds.attrs[_pointing_center].copy()
103
- telpos = {}
104
- telpos["refer"] = xds.attrs["telescope"]["position"]["ellipsoid"]
105
- if xds.attrs["telescope"]["position"]["ellipsoid"] == "GRS80":
106
- telpos["refer"] = "ITRF"
107
- for i in range(3):
108
- telpos[f"m{i}"] = {
109
- "unit": xds.attrs["telescope"]["position"]["units"][i],
110
- "value": xds.attrs["telescope"]["position"]["value"][i],
111
- }
112
- telpos["type"] = "position"
113
- coord["telescopeposition"] = telpos
103
+ if "position" in xds.attrs["telescope"]:
104
+ telpos = {}
105
+ telpos["refer"] = xds.attrs["telescope"]["position"]["ellipsoid"]
106
+ if xds.attrs["telescope"]["position"]["ellipsoid"] == "GRS80":
107
+ telpos["refer"] = "ITRF"
108
+ for i in range(3):
109
+ telpos[f"m{i}"] = {
110
+ "unit": xds.attrs["telescope"]["position"]["units"][i],
111
+ "value": xds.attrs["telescope"]["position"]["value"][i],
112
+ }
113
+ telpos["type"] = "position"
114
+ coord["telescopeposition"] = telpos
114
115
  if "l" in xds.coords:
115
116
  coord["direction0"] = _compute_direction_dict(xds)
116
117
  else:
@@ -15,7 +15,7 @@ from ..common import (
15
15
  _image_type,
16
16
  _l_m_attr_notes,
17
17
  )
18
- from ...._utils.common import _deg_to_rad
18
+ from xradio._utils.coord_math import _deg_to_rad
19
19
  import copy
20
20
  import dask
21
21
  import dask.array as da
@@ -166,7 +166,7 @@ def _xds_direction_attrs_from_header(helpers: dict, header) -> dict:
166
166
  ref_sys = header["RADESYS"]
167
167
  ref_eqx = header["EQUINOX"]
168
168
  if ref_sys == "FK5" and ref_eqx == 2000:
169
- ref_eqx = "J2000"
169
+ ref_eqx = "J2000.0"
170
170
  helpers["ref_sys"] = ref_sys
171
171
  helpers["ref_eqx"] = ref_eqx
172
172
  # fits does not support conversion frames
@@ -237,21 +237,22 @@ def _get_telescope_metadata(helpers: dict, header) -> dict:
237
237
  # The helpers dict is modified in place. header is not modified
238
238
  tel = {}
239
239
  tel["name"] = header["TELESCOP"]
240
- x = header["OBSGEO-X"]
241
- y = header["OBSGEO-Y"]
242
- z = header["OBSGEO-Z"]
243
- xyz = np.array([x, y, z])
244
- r = np.sqrt(np.sum(xyz * xyz))
245
- lat = np.arcsin(z / r)
246
- long = np.arctan2(y, x)
247
- tel["position"] = {
248
- "type": "position",
249
- # I haven't seen a FITS keyword for reference frame of telescope posiiton
250
- "ellipsoid": "GRS80",
251
- "units": ["rad", "rad", "m"],
252
- "value": np.array([long, lat, r]),
253
- }
254
- helpers["tel_pos"] = tel["position"]
240
+ if "OBSGEO-x" in header:
241
+ x = header["OBSGEO-X"]
242
+ y = header["OBSGEO-Y"]
243
+ z = header["OBSGEO-Z"]
244
+ xyz = np.array([x, y, z])
245
+ r = np.sqrt(np.sum(xyz * xyz))
246
+ lat = np.arcsin(z / r)
247
+ long = np.arctan2(y, x)
248
+ tel["position"] = {
249
+ "type": "position",
250
+ # I haven't seen a FITS keyword for reference frame of telescope posiiton
251
+ "ellipsoid": "GRS80",
252
+ "units": ["rad", "rad", "m"],
253
+ "value": np.array([long, lat, r]),
254
+ }
255
+ helpers["tel_pos"] = tel["position"]
255
256
  return tel
256
257
 
257
258
 
@@ -148,7 +148,9 @@ def write_binary_blob_to_disk(arr, file_path, compressor):
148
148
 
149
149
 
150
150
  def write_to_lustre_chunked(
151
- file_path, compressed_arr, chunk_size=1024 * 1024 * 128
151
+ file_path,
152
+ compressed_arr,
153
+ chunk_size=1024 * 1024 * 128,
152
154
  ): # 128 MiB chunks
153
155
  """
154
156
  Writes compressed data to a Lustre file path with chunking.
@@ -158,10 +160,18 @@ def write_to_lustre_chunked(
158
160
  compressed_arr: Compressed data array to write.
159
161
  chunk_size: Size of each data chunk in bytes (default: 128 MiB).
160
162
  """
161
- with open(file_path, "wb") as f:
162
- for i in range(0, len(compressed_arr), chunk_size):
163
- chunk = compressed_arr[i : i + chunk_size]
164
- f.write(chunk)
163
+ fs, items = _get_file_system_and_items(file_path.rsplit("/", 1)[0])
164
+
165
+ if isinstance(fs, s3fs.core.S3FileSystem):
166
+ with fs.open(file_path, "wb") as f:
167
+ for i in range(0, len(compressed_arr), chunk_size):
168
+ chunk = compressed_arr[i : i + chunk_size]
169
+ f.write(chunk)
170
+ else:
171
+ with open(file_path, "wb") as f:
172
+ for i in range(0, len(compressed_arr), chunk_size):
173
+ chunk = compressed_arr[i : i + chunk_size]
174
+ f.write(chunk)
165
175
 
166
176
 
167
177
  def read_binary_blob_from_disk(file_path, compressor, dtype=np.float64):
@@ -237,6 +247,7 @@ def write_json_file(data, file_path):
237
247
  Returns:
238
248
  - None
239
249
  """
250
+
240
251
  with open(file_path, "w") as file:
241
252
  json.dump(
242
253
  data,
@@ -385,13 +396,19 @@ def write_chunk(img_xds, meta, parallel_dims_chunk_id, compressor, image_file):
385
396
  else:
386
397
  array = img_xds[data_variable_name].values
387
398
 
388
- z_chunk = zarr.open(
389
- os.path.join(image_file, data_variable_name, chunk_name),
390
- mode="a",
391
- shape=meta["shape"],
392
- chunks=meta["chunks"],
393
- dtype=meta["dtype"],
399
+ write_binary_blob_to_disk(
400
+ array,
401
+ file_path=os.path.join(image_file, data_variable_name, chunk_name),
394
402
  compressor=compressor,
395
403
  )
396
404
 
397
- return z_chunk
405
+ # z_chunk = zarr.open(
406
+ # os.path.join(image_file, data_variable_name, chunk_name),
407
+ # mode="a",
408
+ # shape=meta["shape"],
409
+ # chunks=meta["chunks"],
410
+ # dtype=meta["dtype"],
411
+ # compressor=compressor,
412
+ # )
413
+
414
+ # return z_chunk
@@ -5,7 +5,7 @@ import dask.array as da
5
5
  import numpy as np
6
6
  from typing import Dict, List
7
7
  import xarray as xr
8
- from ..._utils.common import _deg_to_rad
8
+ from xradio._utils.coord_math import _deg_to_rad
9
9
 
10
10
  _c = 2.99792458e08 * u.m / u.s
11
11
  # OPTICAL = Z
@@ -3,7 +3,7 @@ import numpy as np
3
3
  import xarray as xr
4
4
  from typing import List, Union
5
5
  from .common import _c, _compute_world_sph_dims, _l_m_attr_notes
6
- from ..._utils.common import _deg_to_rad
6
+ from xradio._utils.coord_math import _deg_to_rad
7
7
 
8
8
 
9
9
  def _input_checks(
@@ -1,15 +1,18 @@
1
1
  from .processing_set import ProcessingSet
2
2
  from .open_processing_set import open_processing_set
3
- from .load_processing_set import load_processing_set
3
+ from .load_processing_set import load_processing_set, ProcessingSetIterator
4
4
  from .convert_msv2_to_processing_set import convert_msv2_to_processing_set
5
+ from .measurement_set_xds import MeasurementSetXds
5
6
 
6
- from .schema import VisibilityXds
7
+ from .schema import SpectrumXds, VisibilityXds
7
8
 
8
9
  __all__ = [
10
+ "ProcessingSet",
11
+ "MeasurementSetXds",
9
12
  "open_processing_set",
10
13
  "load_processing_set",
14
+ "ProcessingSetIterator",
11
15
  "convert_msv2_to_processing_set",
16
+ "SpectrumXds",
12
17
  "VisibilityXds",
13
- "PointingXds",
14
- "AntennaXds",
15
18
  ]
@@ -0,0 +1,5 @@
1
+ from . import msv2
2
+ from . import zarr
3
+ from . import _utils
4
+
5
+ __all__ = ["msv2", "zarr", "_utils"]
@@ -12,7 +12,7 @@ from .read_main_table import get_partition_ids, redim_id_data_vars, rename_vars
12
12
  from .read import add_units_measures, convert_casacore_time, extract_table_attributes
13
13
  from .write import revert_time
14
14
  from .table_query import open_query, open_table_ro
15
- from xradio.correlated_data._utils._ms._tables.read_main_table import (
15
+ from xradio.measurement_set._utils._ms._tables.read_main_table import (
16
16
  get_baselines,
17
17
  get_baseline_indices,
18
18
  )
@@ -12,7 +12,7 @@ import astropy.units
12
12
  from casacore import tables
13
13
 
14
14
  from .table_query import open_query, open_table_ro
15
- from ....._utils.common import get_pad_value
15
+ from xradio._utils.list_and_array import get_pad_value
16
16
 
17
17
  CASACORE_TO_PD_TIME_CORRECTION = 3_506_716_800.0
18
18
  SECS_IN_DAY = 86400