xradio 0.0.25__tar.gz → 0.0.27__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 (78) hide show
  1. {xradio-0.0.25/src/xradio.egg-info → xradio-0.0.27}/PKG-INFO +2 -1
  2. {xradio-0.0.25 → xradio-0.0.27}/pyproject.toml +2 -1
  3. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/_utils/zarr/common.py +7 -2
  4. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_casacore/xds_from_casacore.py +1 -1
  5. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_casacore/xds_to_casacore.py +6 -6
  6. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_fits/xds_from_fits.py +1 -1
  7. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/casacore.py +2 -2
  8. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/common.py +4 -0
  9. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/read_main_table.py +2 -4
  10. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/load_processing_set.py +63 -20
  11. xradio-0.0.27/src/xradio/vis/read_processing_set.py +150 -0
  12. {xradio-0.0.25 → xradio-0.0.27/src/xradio.egg-info}/PKG-INFO +2 -1
  13. {xradio-0.0.25 → xradio-0.0.27}/src/xradio.egg-info/requires.txt +1 -0
  14. xradio-0.0.25/src/xradio/vis/read_processing_set.py +0 -85
  15. {xradio-0.0.25 → xradio-0.0.27}/LICENSE.txt +0 -0
  16. {xradio-0.0.25 → xradio-0.0.27}/MANIFEST.in +0 -0
  17. {xradio-0.0.25 → xradio-0.0.27}/README.md +0 -0
  18. {xradio-0.0.25 → xradio-0.0.27}/setup.cfg +0 -0
  19. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/__init__.py +0 -0
  20. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/_utils/__init__.py +0 -0
  21. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/_utils/_casacore/tables.py +0 -0
  22. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/_utils/common.py +0 -0
  23. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/_utils/zarr/__init__.py +0 -0
  24. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/__init__.py +0 -0
  25. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/__init__.py +0 -0
  26. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_casacore/__init__.py +0 -0
  27. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_casacore/common.py +0 -0
  28. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_zarr/common.py +0 -0
  29. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_zarr/xds_from_zarr.py +0 -0
  30. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_zarr/xds_to_zarr.py +0 -0
  31. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/_zarr/zarr_low_level.py +0 -0
  32. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/fits.py +0 -0
  33. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/image_factory.py +0 -0
  34. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/_util/zarr.py +0 -0
  35. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/image/image.py +0 -0
  36. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/schema/__init__.py +0 -0
  37. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/schema/bases.py +0 -0
  38. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/schema/check.py +0 -0
  39. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/schema/dataclass.py +0 -0
  40. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/schema/metamodel.py +0 -0
  41. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/schema/typing.py +0 -0
  42. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/__init__.py +0 -0
  43. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_processing_set.py +0 -0
  44. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/__init__.py +0 -0
  45. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/load.py +0 -0
  46. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/load_main_table.py +0 -0
  47. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/read.py +0 -0
  48. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/read_subtables.py +0 -0
  49. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/table_query.py +0 -0
  50. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/write.py +0 -0
  51. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/_tables/write_exp_api.py +0 -0
  52. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/chunks.py +0 -0
  53. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/conversion.py +0 -0
  54. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/descr.py +0 -0
  55. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/msv2_msv3.py +0 -0
  56. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/msv2_to_msv4_meta.py +0 -0
  57. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/msv4_infos.py +0 -0
  58. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/msv4_sub_xdss.py +0 -0
  59. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/optimised_functions.py +0 -0
  60. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/partition_queries.py +0 -0
  61. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/partitions.py +0 -0
  62. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_ms/subtables.py +0 -0
  63. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_utils/cds.py +0 -0
  64. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_utils/partition_attrs.py +0 -0
  65. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_utils/stokes_types.py +0 -0
  66. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_utils/xds_helper.py +0 -0
  67. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_zarr/encoding.py +0 -0
  68. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_zarr/read.py +0 -0
  69. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/_zarr/write.py +0 -0
  70. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/ms.py +0 -0
  71. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/ms_column_descriptions_dicts.py +0 -0
  72. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/_vis_utils/zarr.py +0 -0
  73. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/convert_msv2_to_processing_set.py +0 -0
  74. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/model.py +0 -0
  75. {xradio-0.0.25 → xradio-0.0.27}/src/xradio/vis/vis_io.py +0 -0
  76. {xradio-0.0.25 → xradio-0.0.27}/src/xradio.egg-info/SOURCES.txt +0 -0
  77. {xradio-0.0.25 → xradio-0.0.27}/src/xradio.egg-info/dependency_links.txt +0 -0
  78. {xradio-0.0.25 → xradio-0.0.27}/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.25
3
+ Version: 0.0.27
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
@@ -47,6 +47,7 @@ Requires-Dist: prettytable
47
47
  Requires-Dist: pytest
48
48
  Requires-Dist: pytest-cov
49
49
  Requires-Dist: pytest-html
50
+ Requires-Dist: s3fs
50
51
  Requires-Dist: scipy
51
52
  Requires-Dist: tqdm
52
53
  Requires-Dist: xarray
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xradio"
3
- version = "0.0.25"
3
+ version = "0.0.27"
4
4
  description = "Xarray Radio Astronomy Data IO"
5
5
  authors = [
6
6
  {name = "Jan-Willem Steeb", email="jsteeb@nrao.edu"},
@@ -22,6 +22,7 @@ dependencies = [
22
22
  'pytest',
23
23
  'pytest-cov',
24
24
  'pytest-html',
25
+ 's3fs',
25
26
  'scipy',
26
27
  'tqdm',
27
28
  'xarray',
@@ -1,9 +1,10 @@
1
1
  import copy
2
2
  import xarray as xr
3
3
  import zarr
4
+ import s3fs
4
5
 
5
6
 
6
- def _open_dataset(store, xds_isel=None, data_variables=None, load=False):
7
+ def _open_dataset(store, xds_isel=None, data_variables=None, load=False, **kwargs):
7
8
  """
8
9
 
9
10
  Parameters
@@ -25,7 +26,11 @@ def _open_dataset(store, xds_isel=None, data_variables=None, load=False):
25
26
 
26
27
  import dask
27
28
 
28
- xds = xr.open_zarr(store)
29
+ if "s3" in kwargs.keys():
30
+ mapping = s3fs.S3Map(root=store, s3=kwargs["s3"], check=False)
31
+ xds = xr.open_zarr(store=mapping)
32
+ else:
33
+ xds = xr.open_zarr(store)
29
34
 
30
35
  if xds_isel is not None:
31
36
  xds = xds.isel(xds_isel)
@@ -106,7 +106,7 @@ def _add_sky_or_aperture(
106
106
  unit = casa_image.unit()
107
107
  xda.attrs[_image_type] = image_type
108
108
  xda.attrs["units"] = unit
109
- name = "sky" if has_sph_dims else "aperture"
109
+ name = "SKY" if has_sph_dims else "APERTURE"
110
110
  xda = xda.rename(name)
111
111
  xds[xda.name] = xda
112
112
  return xds
@@ -8,7 +8,7 @@ from astropy.coordinates import Angle
8
8
  from casacore import tables
9
9
 
10
10
  from .common import _active_mask, _create_new_image, _object_name, _pointing_center
11
- from ..common import _compute_sky_reference_pixel, _doppler_types
11
+ from ..common import _aperture_or_sky, _compute_sky_reference_pixel, _doppler_types
12
12
  from ...._utils._casacore.tables import open_table_rw
13
13
 
14
14
 
@@ -168,7 +168,7 @@ def _history_from_xds(xds: xr.Dataset, image: str) -> None:
168
168
 
169
169
  def _imageinfo_dict_from_xds(xds: xr.Dataset) -> dict:
170
170
  ii = {}
171
- ap_sky = "sky" if "l" in xds.coords else "aperture"
171
+ ap_sky = _aperture_or_sky(xds)
172
172
  ii["image_type"] = (
173
173
  xds[ap_sky].attrs["image_type"] if "image_type" in xds[ap_sky].attrs else ""
174
174
  )
@@ -208,12 +208,12 @@ def _imageinfo_dict_from_xds(xds: xr.Dataset) -> dict:
208
208
 
209
209
 
210
210
  def _write_casa_data(xds: xr.Dataset, image_full_path: str) -> None:
211
- sky_ap = "sky" if "sky" in xds else "aperture"
211
+ sky_ap = _aperture_or_sky(xds)
212
212
  if xds[sky_ap].shape[0] != 1:
213
213
  raise RuntimeError("XDS can only be converted if it has exactly one time plane")
214
214
  trans_coords = (
215
215
  ("frequency", "polarization", "m", "l")
216
- if sky_ap == "sky"
216
+ if sky_ap == "SKY"
217
217
  else ("frequency", "polarization", "v", "u")
218
218
  )
219
219
  casa_image_shape = xds[sky_ap].isel(time=0).transpose(*trans_coords).shape[::-1]
@@ -312,7 +312,7 @@ def _write_initial_image(
312
312
  ) -> None:
313
313
  if not maskname:
314
314
  maskname = ""
315
- for dv in ["sky", "aperture"]:
315
+ for dv in ["SKY", "APERTURE"]:
316
316
  if dv in xds.data_vars:
317
317
  value = xds[dv][0, 0, 0, 0, 0].values.item()
318
318
  if xds[dv][0, 0, 0, 0, 0].values.dtype == "float32":
@@ -352,7 +352,7 @@ def _write_pixels(
352
352
  value: xr.DataArray = None,
353
353
  ) -> None:
354
354
  flip = False
355
- if v == "sky" or v == "aperture":
355
+ if v == "SKY" or v == "APERTURE":
356
356
  filename = image_full_path
357
357
  else:
358
358
  # mask
@@ -685,7 +685,7 @@ def _add_sky_or_aperture(
685
685
  unit = helpers["bunit"]
686
686
  xda.attrs[_image_type] = image_type
687
687
  xda.attrs["units"] = unit
688
- name = "sky" if has_sph_dims else "aperture"
688
+ name = "SKY" if has_sph_dims else "APERTURE"
689
689
  xda = xda.rename(name)
690
690
  xds[xda.name] = xda
691
691
  if helpers["has_mask"]:
@@ -30,7 +30,7 @@ from ._casacore.xds_to_casacore import (
30
30
  _imageinfo_dict_from_xds,
31
31
  _write_casa_data,
32
32
  )
33
- from .common import _get_xds_dim_order, _dask_arrayize_dv
33
+ from .common import _aperture_or_sky, _get_xds_dim_order, _dask_arrayize_dv
34
34
 
35
35
  warnings.filterwarnings("ignore", category=FutureWarning)
36
36
 
@@ -104,7 +104,7 @@ def _xds_to_casa_image(xds: xr.Dataset, imagename: str) -> None:
104
104
  image_full_path = os.path.expanduser(imagename)
105
105
  _write_casa_data(xds, image_full_path)
106
106
  # create coordinates
107
- ap_sky = "sky" if "sky" in xds.data_vars else "aperture"
107
+ ap_sky = _aperture_or_sky(xds)
108
108
  coord = _coord_dict_from_xds(xds)
109
109
  ii = _imageinfo_dict_from_xds(xds)
110
110
  units = xds[ap_sky].attrs["units"] if "units" in xds[ap_sky].attrs else None
@@ -13,6 +13,10 @@ _doppler_types = ["RADIO", "Z", "RATIO", "BETA", "GAMMA"]
13
13
  _image_type = "image_type"
14
14
 
15
15
 
16
+ def _aperture_or_sky(xds: xr.Dataset) -> str:
17
+ return "SKY" if "SKY" in xds.data_vars or "l" in xds.coords else "APERTURE"
18
+
19
+
16
20
  def _get_xds_dim_order(has_sph: bool) -> list:
17
21
  dimorder = ["time", "polarization", "frequency"]
18
22
  dir_lin = ["l", "m"] if has_sph else ["u", "v"]
@@ -195,10 +195,8 @@ def read_main_table_chunks(
195
195
  n_baseline_chunks = chunks[1]
196
196
  # loop over time chunks
197
197
  for time_chunk in range(0, n_unique_times, n_time_chunks):
198
- time_start = (unique_times[time_chunk] - tol,)
199
- time_end = (
200
- unique_times[min(n_unique_times, time_chunk + n_time_chunks) - 1] + tol
201
- )
198
+ time_start = unique_times[time_chunk] - tol
199
+ time_end = unique_times[min(n_unique_times, time_chunk + n_time_chunks) - 1] + tol
202
200
 
203
201
  # chunk time length
204
202
  ctlen = min(n_unique_times, time_chunk + n_time_chunks) - time_chunk
@@ -11,13 +11,13 @@ def load_processing_set(
11
11
  sel_parms: dict,
12
12
  data_variables: Union[list, None] = None,
13
13
  load_sub_datasets: bool = True,
14
- )->processing_set:
14
+ ) -> processing_set:
15
15
  """Loads a processing set into memory.
16
16
 
17
17
  Parameters
18
18
  ----------
19
19
  ps_store : str
20
- String of the path and name of the processing set. For example '/users/user_1/uid___A002_Xf07bba_Xbe5c_target.lsrk.vis.zarr'.
20
+ String of the path and name of the processing set. For example '/users/user_1/uid___A002_Xf07bba_Xbe5c_target.lsrk.vis.zarr' for a file stored on a local file system, or 's3://viper-test-data/Antennae_North.cal.lsrk.split.vis.zarr/' for a file in AWS object storage.
21
21
  sel_parms : dict
22
22
  A dictionary where the keys are the names of the ms_xds's and the values are slice_dicts.
23
23
  slice_dicts: A dictionary where the keys are the dimension names and the values are slices.
@@ -37,26 +37,69 @@ def load_processing_set(
37
37
  Returns
38
38
  -------
39
39
  processing_set
40
- In memory representation of processing set (data is represented by Dask.arrays).
41
- """
40
+ In memory representation of processing set (data is represented by Dask.arrays).
41
+ """
42
42
  from xradio._utils.zarr.common import _open_dataset
43
+ import s3fs
44
+ from botocore.exceptions import NoCredentialsError
43
45
 
46
+ s3 = None
44
47
  ps = processing_set()
45
48
  for ms_dir_name, ms_xds_isel in sel_parms.items():
46
- xds = _open_dataset(
47
- os.path.join(ps_store, ms_dir_name, "MAIN"),
48
- ms_xds_isel,
49
- data_variables,
50
- load=True,
51
- )
52
-
53
- if load_sub_datasets:
54
- from xradio.vis.read_processing_set import _read_sub_xds
55
-
56
- xds.attrs = {
57
- **xds.attrs,
58
- **_read_sub_xds(os.path.join(ps_store, ms_dir_name), load=True),
59
- }
49
+
50
+ # before the _open_dataset call, check if dealing with an S3 bucket URL
51
+ if ps_store.startswith("s3"):
52
+ if not ps_store.endswith("/"):
53
+ # just for consistency, as there is no os.path equivalent in s3fs
54
+ ps_store = ps_store + "/"
55
+
56
+ try:
57
+ s3 = s3fs.S3FileSystem(anon=False, requester_pays=False)
58
+
59
+ main_xds = ps_store + ms_dir_name + "/MAIN"
60
+ xds = _open_dataset(
61
+ main_xds, ms_xds_isel, data_variables, load=True, s3=s3
62
+ )
63
+
64
+ if load_sub_datasets:
65
+ from xradio.vis.read_processing_set import _read_sub_xds
66
+
67
+ xds.attrs = {
68
+ **xds.attrs,
69
+ **_read_sub_xds(
70
+ os.path.join(ps_store, ms_dir_name), load=True, s3=s3
71
+ ),
72
+ }
73
+
74
+ except (NoCredentialsError, PermissionError) as e:
75
+ # only public, read-only buckets will be accessible
76
+ s3 = s3fs.S3FileSystem(anon=True)
77
+
78
+ main_xds = ps_store + ms_dir_name + "/MAIN"
79
+ xds = _open_dataset(
80
+ main_xds, ms_xds_isel, data_variables, load=True, s3=s3
81
+ )
82
+
83
+ if load_sub_datasets:
84
+ from xradio.vis.read_processing_set import _read_sub_xds
85
+
86
+ xds.attrs = {
87
+ **xds.attrs,
88
+ **_read_sub_xds(
89
+ os.path.join(ps_store, ms_dir_name), load=True, s3=s3
90
+ ),
91
+ }
92
+ else:
93
+ # fall back to the default case of assuming the files are on local disk
94
+ main_xds = os.path.join(ps_store, ms_dir_name, "MAIN")
95
+ xds = _open_dataset(main_xds, ms_xds_isel, data_variables, load=True)
96
+ if load_sub_datasets:
97
+ from xradio.vis.read_processing_set import _read_sub_xds
98
+
99
+ xds.attrs = {
100
+ **xds.attrs,
101
+ **_read_sub_xds(os.path.join(ps_store, ms_dir_name), load=True),
102
+ }
60
103
 
61
104
  ps[ms_dir_name] = xds
62
105
  return ps
@@ -94,7 +137,7 @@ class processing_set_iterator:
94
137
  The list of data variables to load into memory for example ['VISIBILITY', 'WEIGHT, 'FLAGS']. By default None which will load all data variables into memory.
95
138
  load_sub_datasets : bool, optional
96
139
  If true sub-datasets (for example weather_xds, antenna_xds, pointing_xds, ...) will be loaded into memory, by default True.
97
- """
140
+ """
98
141
 
99
142
  self.input_data = input_data
100
143
  self.input_data_store = input_data_store
@@ -124,4 +167,4 @@ class processing_set_iterator:
124
167
  else:
125
168
  xds = self.input_data[xds_name] # In memory
126
169
 
127
- return xds
170
+ return xds
@@ -0,0 +1,150 @@
1
+ import os
2
+ import xarray as xr
3
+ from ._processing_set import processing_set
4
+ import graphviper.utils.logger as logger
5
+ from xradio._utils.zarr.common import _open_dataset
6
+ import s3fs
7
+ from botocore.exceptions import NoCredentialsError
8
+
9
+
10
+ def read_processing_set(
11
+ ps_store: str, intents: list = None, fields: str = None
12
+ ) -> processing_set:
13
+ """Creates a lazy representation of a Processing Set (only meta-data is loaded into memory).
14
+
15
+ Parameters
16
+ ----------
17
+ ps_store : str
18
+ String of the path and name of the processing set. For example '/users/user_1/uid___A002_Xf07bba_Xbe5c_target.lsrk.vis.zarr'.
19
+ intents : list, optional
20
+ A list of the intents to be read for example ['OBSERVE_TARGET#ON_SOURCE']. The intents in a processing set can be seem by calling processing_set.summary().
21
+ By default None, which will read all intents.
22
+ fields : str, optional
23
+ The list of field names that will be read, by default None which will read all fields.
24
+
25
+ Returns
26
+ -------
27
+ processing_set
28
+ Lazy representation of processing set (data is represented by Dask.arrays).
29
+ """
30
+ s3 = None
31
+ ps_store_is_s3dir = None
32
+
33
+ if os.path.isdir(ps_store):
34
+ ps_store_is_s3dir = False
35
+ # default to assuming the data are accessible on local file system
36
+ items = os.listdir(ps_store)
37
+
38
+ elif ps_store.startswith("s3"):
39
+ # only if not found locally, check if dealing with an S3 bucket URL
40
+ ps_store_is_s3dir = True
41
+ if not ps_store.endswith("/"):
42
+ # just for consistency, as there is no os.path equivalent in s3fs
43
+ ps_store = ps_store + "/"
44
+
45
+ try:
46
+ # initialize the S3 "file system", first attempting to use pre-configured credentials
47
+ s3 = s3fs.S3FileSystem(anon=False, requester_pays=False)
48
+
49
+ items = [bd.split(sep="/")[-1] for bd in s3.listdir(ps_store, detail=False)]
50
+
51
+ except (NoCredentialsError, PermissionError) as e:
52
+ # only public, read-only buckets will be accessible
53
+ # we will want to add messaging and error handling here
54
+ s3 = s3fs.S3FileSystem(anon=True)
55
+
56
+ items = [bd.split(sep="/")[-1] for bd in s3.listdir(ps_store, detail=False)]
57
+
58
+ else:
59
+ raise (
60
+ FileNotFoundError,
61
+ f"Could not find {ps_store} either locally or in the cloud.",
62
+ )
63
+
64
+ ms_xds = xr.Dataset()
65
+ ps = processing_set()
66
+ data_group = "base"
67
+ for ms_dir_name in items:
68
+ if "ddi" in ms_dir_name:
69
+ if ps_store_is_s3dir:
70
+ store_path = ps_store + ms_dir_name
71
+ store_path_main = store_path + "/MAIN"
72
+ else:
73
+ store_path_main = os.path.join(ps_store, ms_dir_name, "MAIN")
74
+ store_path = os.path.split(store_path_main)[0]
75
+ if s3 is not None:
76
+ xds = _open_dataset(store_path_main, s3=s3)
77
+ else:
78
+ xds = _open_dataset(store_path_main)
79
+
80
+ if (intents is None) or (xds.attrs["intent"] in intents):
81
+ data_name = _get_data_name(xds, data_group)
82
+
83
+ if (fields is None) or (
84
+ xds[data_name].attrs["field_info"]["name"] in fields
85
+ ):
86
+ if s3 is not None:
87
+ xds.attrs = {
88
+ **xds.attrs,
89
+ **_read_sub_xds(store_path, s3=s3),
90
+ }
91
+ ps[ms_dir_name] = xds
92
+ else:
93
+ xds.attrs = {
94
+ **xds.attrs,
95
+ **_read_sub_xds(store_path),
96
+ }
97
+ ps[ms_dir_name] = xds
98
+
99
+ return ps
100
+
101
+
102
+ def _read_sub_xds(ms_store, load=False, **kwargs):
103
+ sub_xds_dict = {}
104
+
105
+ sub_xds = {
106
+ "antenna_xds": "ANTENNA",
107
+ }
108
+ for sub_xds_key, sub_xds_name in sub_xds.items():
109
+ if "s3" in kwargs.keys():
110
+ joined_store = ms_store + "/" + sub_xds_name
111
+ sub_xds_dict[sub_xds_key] = _open_dataset(
112
+ joined_store, load=load, s3=kwargs["s3"]
113
+ )
114
+ else:
115
+ sub_xds_dict[sub_xds_key] = _open_dataset(
116
+ os.path.join(ms_store, sub_xds_name), load=load
117
+ )
118
+
119
+ optional_sub_xds = {
120
+ "weather_xds": "WEATHER",
121
+ "pointing_xds": "POINTING",
122
+ }
123
+ for sub_xds_key, sub_xds_name in optional_sub_xds.items():
124
+ sub_xds_path = os.path.join(ms_store, sub_xds_name)
125
+ if os.path.isdir(sub_xds_path):
126
+ sub_xds_dict[sub_xds_key] = _open_dataset(sub_xds_path, load=load)
127
+ elif "s3" in kwargs.keys():
128
+ joined_store = ms_store + "/" + sub_xds_name
129
+ if kwargs["s3"].isdir(joined_store):
130
+ sub_xds_dict[sub_xds_key] = _open_dataset(
131
+ joined_store, load=load, s3=kwargs["s3"]
132
+ )
133
+
134
+ return sub_xds_dict
135
+
136
+
137
+ def _get_data_name(xds, data_group):
138
+ if "visibility" in xds.attrs["data_groups"][data_group]:
139
+ data_name = xds.attrs["data_groups"][data_group]["visibility"]
140
+ elif "spectrum" in xds.attrs["data_groups"][data_group]:
141
+ data_name = xds.attrs["data_groups"][data_group]["spectrum"]
142
+ else:
143
+ error_message = (
144
+ "No Visibility or Spectrum data variable found in data_group "
145
+ + data_group
146
+ + "."
147
+ )
148
+ logger.exception(error_message)
149
+ raise ValueError(error_message)
150
+ return data_name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xradio
3
- Version: 0.0.25
3
+ Version: 0.0.27
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
@@ -47,6 +47,7 @@ Requires-Dist: prettytable
47
47
  Requires-Dist: pytest
48
48
  Requires-Dist: pytest-cov
49
49
  Requires-Dist: pytest-html
50
+ Requires-Dist: s3fs
50
51
  Requires-Dist: scipy
51
52
  Requires-Dist: tqdm
52
53
  Requires-Dist: xarray
@@ -10,6 +10,7 @@ prettytable
10
10
  pytest
11
11
  pytest-cov
12
12
  pytest-html
13
+ s3fs
13
14
  scipy
14
15
  tqdm
15
16
  xarray
@@ -1,85 +0,0 @@
1
- import os
2
- import xarray as xr
3
- from ._processing_set import processing_set
4
- import graphviper.utils.logger as logger
5
- from xradio._utils.zarr.common import _open_dataset
6
-
7
-
8
- def read_processing_set(
9
- ps_store: str, intents: list = None, fields: str = None
10
- )->processing_set:
11
- """Creates a lazy representation of a Processing Set (only meta-data is loaded into memory).
12
-
13
- Parameters
14
- ----------
15
- ps_store : str
16
- String of the path and name of the processing set. For example '/users/user_1/uid___A002_Xf07bba_Xbe5c_target.lsrk.vis.zarr'.
17
- intents : list, optional
18
- A list of the intents to be read for example ['OBSERVE_TARGET#ON_SOURCE']. The intents in a processing set can be seem by calling processing_set.summary().
19
- By default None, which will read all intents.
20
- fields : str, optional
21
- The list of field names that will be read, by default None which will read all fields.
22
-
23
- Returns
24
- -------
25
- processing_set
26
- Lazy representation of processing set (data is represented by Dask.arrays).
27
- """
28
- items = os.listdir(ps_store)
29
- ms_xds = xr.Dataset()
30
- ps = processing_set()
31
- data_group = 'base'
32
- for ms_dir_name in items:
33
- if "ddi" in ms_dir_name:
34
- xds = _open_dataset(os.path.join(ps_store, ms_dir_name, "MAIN"))
35
- if (intents is None) or (xds.attrs["intent"] in intents):
36
- data_name = _get_data_name(xds, data_group)
37
-
38
- if (fields is None) or (
39
- xds[data_name].attrs["field_info"]["name"] in fields
40
- ):
41
- xds.attrs = {
42
- **xds.attrs,
43
- **_read_sub_xds(os.path.join(ps_store, ms_dir_name)),
44
- }
45
- ps[ms_dir_name] = xds
46
- return ps
47
-
48
-
49
- def _read_sub_xds(ms_store, load=False):
50
- sub_xds_dict = {}
51
-
52
- sub_xds = {
53
- "antenna_xds": "ANTENNA",
54
- }
55
- for sub_xds_key, sub_xds_name in sub_xds.items():
56
- sub_xds_dict[sub_xds_key] = _open_dataset(
57
- os.path.join(ms_store, sub_xds_name), load=load
58
- )
59
-
60
- optional_sub_xds = {
61
- "weather_xds": "WEATHER",
62
- "pointing_xds": "POINTING",
63
- }
64
- for sub_xds_key, sub_xds_name in optional_sub_xds.items():
65
- sub_xds_path = os.path.join(ms_store, sub_xds_name)
66
- if os.path.isdir(sub_xds_path):
67
- sub_xds_dict[sub_xds_key] = _open_dataset(sub_xds_path, load=load)
68
-
69
- return sub_xds_dict
70
-
71
-
72
- def _get_data_name(xds, data_group):
73
- if "visibility" in xds.attrs["data_groups"][data_group]:
74
- data_name = xds.attrs["data_groups"][data_group]["visibility"]
75
- elif "spectrum" in xds.attrs["data_groups"][data_group]:
76
- data_name = xds.attrs["data_groups"][data_group]["spectrum"]
77
- else:
78
- error_message = (
79
- "No Visibility or Spectrum data variable found in data_group "
80
- + data_group
81
- + "."
82
- )
83
- logger.exception(error_message)
84
- raise ValueError(error_message)
85
- return data_name
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes