xradio 0.0.56__py3-none-any.whl → 0.0.59__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 (63) hide show
  1. xradio/__init__.py +2 -2
  2. xradio/_utils/_casacore/casacore_from_casatools.py +12 -2
  3. xradio/_utils/_casacore/tables.py +1 -0
  4. xradio/_utils/coord_math.py +22 -23
  5. xradio/_utils/dict_helpers.py +76 -11
  6. xradio/_utils/schema.py +5 -2
  7. xradio/_utils/zarr/common.py +1 -73
  8. xradio/image/_util/_casacore/xds_from_casacore.py +49 -33
  9. xradio/image/_util/_casacore/xds_to_casacore.py +41 -14
  10. xradio/image/_util/_fits/xds_from_fits.py +146 -35
  11. xradio/image/_util/casacore.py +4 -3
  12. xradio/image/_util/common.py +4 -4
  13. xradio/image/_util/image_factory.py +8 -8
  14. xradio/image/image.py +45 -5
  15. xradio/measurement_set/__init__.py +19 -9
  16. xradio/measurement_set/_utils/__init__.py +1 -3
  17. xradio/measurement_set/_utils/_msv2/__init__.py +0 -0
  18. xradio/measurement_set/_utils/_msv2/_tables/read.py +17 -76
  19. xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py +2 -685
  20. xradio/measurement_set/_utils/_msv2/conversion.py +174 -156
  21. xradio/measurement_set/_utils/_msv2/create_antenna_xds.py +9 -16
  22. xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py +128 -222
  23. xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py +1 -2
  24. xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +8 -7
  25. xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +31 -74
  26. xradio/measurement_set/_utils/_msv2/partition_queries.py +1 -261
  27. xradio/measurement_set/_utils/_msv2/subtables.py +0 -107
  28. xradio/measurement_set/_utils/_utils/interpolate.py +60 -0
  29. xradio/measurement_set/_utils/_zarr/encoding.py +2 -7
  30. xradio/measurement_set/convert_msv2_to_processing_set.py +0 -2
  31. xradio/measurement_set/load_processing_set.py +2 -2
  32. xradio/measurement_set/measurement_set_xdt.py +20 -16
  33. xradio/measurement_set/open_processing_set.py +1 -3
  34. xradio/measurement_set/processing_set_xdt.py +54 -841
  35. xradio/measurement_set/schema.py +122 -132
  36. xradio/schema/check.py +95 -101
  37. xradio/schema/dataclass.py +159 -22
  38. xradio/schema/export.py +99 -0
  39. xradio/schema/metamodel.py +51 -16
  40. xradio/schema/typing.py +5 -5
  41. xradio/sphinx/schema_table.py +41 -77
  42. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/METADATA +20 -5
  43. xradio-0.0.59.dist-info/RECORD +65 -0
  44. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/WHEEL +1 -1
  45. xradio/image/_util/fits.py +0 -13
  46. xradio/measurement_set/_utils/_msv2/_tables/load.py +0 -66
  47. xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py +0 -490
  48. xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py +0 -398
  49. xradio/measurement_set/_utils/_msv2/_tables/write.py +0 -323
  50. xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py +0 -388
  51. xradio/measurement_set/_utils/_msv2/chunks.py +0 -115
  52. xradio/measurement_set/_utils/_msv2/descr.py +0 -165
  53. xradio/measurement_set/_utils/_msv2/msv2_msv3.py +0 -7
  54. xradio/measurement_set/_utils/_msv2/partitions.py +0 -392
  55. xradio/measurement_set/_utils/_utils/cds.py +0 -40
  56. xradio/measurement_set/_utils/_utils/xds_helper.py +0 -404
  57. xradio/measurement_set/_utils/_zarr/read.py +0 -263
  58. xradio/measurement_set/_utils/_zarr/write.py +0 -329
  59. xradio/measurement_set/_utils/msv2.py +0 -106
  60. xradio/measurement_set/_utils/zarr.py +0 -133
  61. xradio-0.0.56.dist-info/RECORD +0 -78
  62. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/licenses/LICENSE.txt +0 -0
  63. {xradio-0.0.56.dist-info → xradio-0.0.59.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,6 @@
1
1
  import pandas as pd
2
2
  from xradio._utils.list_and_array import to_list
3
- import numbers
4
3
  import numpy as np
5
- import toolviper.utils.logger as logger
6
4
  import xarray as xr
7
5
 
8
6
  PS_DATASET_TYPES = {"processing_set"}
@@ -39,7 +37,7 @@ class ProcessingSetXdt:
39
37
  self._xdt = datatree
40
38
  self.meta = {"summary": {}}
41
39
 
42
- def summary(self, data_group: str = "base") -> pd.DataFrame:
40
+ def summary(self, data_group: str = None) -> pd.DataFrame:
43
41
  """
44
42
  Generate and retrieve a summary of the Processing Set.
45
43
 
@@ -50,7 +48,8 @@ class ProcessingSetXdt:
50
48
  Parameters
51
49
  ----------
52
50
  data_group : str, optional
53
- The data group to summarize. Default is "base".
51
+ The data group to summarize. By default the "base" group
52
+ is used (if found), or otherwise the first group found.
54
53
 
55
54
  Returns
56
55
  -------
@@ -58,11 +57,24 @@ class ProcessingSetXdt:
58
57
  A DataFrame containing the summary information of the specified data group.
59
58
  """
60
59
 
60
+ def find_data_group_base_or_first(data_group: str, xdt: xr.DataTree) -> str:
61
+ first_msv4 = next(iter(xdt.values()))
62
+ first_data_groups = first_msv4.attrs["data_groups"]
63
+ if data_group is None:
64
+ data_group = (
65
+ "base"
66
+ if "base" in first_data_groups
67
+ else next(iter(first_data_groups))
68
+ )
69
+ return data_group
70
+
61
71
  if self._xdt.attrs.get("type") not in PS_DATASET_TYPES:
62
72
  raise InvalidAccessorLocation(
63
73
  f"{self._xdt.path} is not a processing set node."
64
74
  )
65
75
 
76
+ data_group = find_data_group_base_or_first(data_group, self._xdt)
77
+
66
78
  if data_group in self.meta["summary"]:
67
79
  return self.meta["summary"][data_group]
68
80
  else:
@@ -130,7 +142,7 @@ class ProcessingSetXdt:
130
142
  if "freq_axis" in self.meta:
131
143
  return self.meta["freq_axis"]
132
144
  else:
133
- spw_ids = []
145
+ spw_names = []
134
146
  freq_axis_list = []
135
147
  frame = self._xdt[next(iter(self._xdt.children))].frequency.attrs[
136
148
  "observer"
@@ -139,15 +151,17 @@ class ProcessingSetXdt:
139
151
  assert (
140
152
  frame == ms_xdt.frequency.attrs["observer"]
141
153
  ), "Frequency reference frame not consistent in Processing Set."
142
- if ms_xdt.frequency.attrs["spectral_window_id"] not in spw_ids:
143
- spw_ids.append(ms_xdt.frequency.attrs["spectral_window_id"])
154
+ if ms_xdt.frequency.attrs["spectral_window_name"] not in spw_names:
155
+ spw_names.append(ms_xdt.frequency.attrs["spectral_window_name"])
144
156
  freq_axis_list.append(ms_xdt.frequency)
145
157
 
146
- freq_axis = xr.concat(freq_axis_list, dim="frequency").sortby("frequency")
158
+ freq_axis = xr.concat(freq_axis_list, dim="frequency", join="outer").sortby(
159
+ "frequency"
160
+ )
147
161
  self.meta["freq_axis"] = freq_axis
148
162
  return self.meta["freq_axis"]
149
163
 
150
- def _summary(self, data_group: str = "base"):
164
+ def _summary(self, data_group: str = None):
151
165
  summary_data = {
152
166
  "name": [],
153
167
  "intents": [],
@@ -155,6 +169,7 @@ class ProcessingSetXdt:
155
169
  "polarization": [],
156
170
  "scan_name": [],
157
171
  "spw_name": [],
172
+ "spw_intent": [],
158
173
  "field_name": [],
159
174
  "source_name": [],
160
175
  "line_name": [],
@@ -171,15 +186,16 @@ class ProcessingSetXdt:
171
186
  summary_data["name"].append(key)
172
187
  summary_data["intents"].append(partition_info["intents"])
173
188
  summary_data["spw_name"].append(partition_info["spectral_window_name"])
189
+ summary_data["spw_intent"].append(partition_info["spectral_window_intent"])
174
190
  summary_data["polarization"].append(value.polarization.values)
175
191
  summary_data["scan_name"].append(partition_info["scan_name"])
176
192
  data_name = value.attrs["data_groups"][data_group]["correlated_data"]
177
193
 
178
194
  if "VISIBILITY" in data_name:
179
- center_name = "FIELD_PHASE_CENTER"
195
+ center_name = "FIELD_PHASE_CENTER_DIRECTION"
180
196
 
181
197
  if "SPECTRUM" in data_name:
182
- center_name = "FIELD_REFERENCE_CENTER"
198
+ center_name = "FIELD_REFERENCE_CENTER_DIRECTION"
183
199
 
184
200
  summary_data["shape"].append(value[data_name].shape)
185
201
 
@@ -255,10 +271,10 @@ class ProcessingSetXdt:
255
271
  Examples
256
272
  --------
257
273
  >>> # Select all MSs with intents 'OBSERVE_TARGET#ON_SOURCE' and polarization 'RR' or 'LL'
258
- >>> selected_ps = ps.query(intents='OBSERVE_TARGET#ON_SOURCE', polarization=['RR', 'LL'])
274
+ >>> selected_ps_xdt = ps_xdt.xr_ps.query(intents='OBSERVE_TARGET#ON_SOURCE', polarization=['RR', 'LL'])
259
275
 
260
276
  >>> # Select all MSs with start_frequency greater than 100 GHz and less than 200 GHz
261
- >>> selected_ps = ps.query(query='start_frequency > 100e9 AND end_frequency < 200e9')
277
+ >>> selected_ps_xdt = ps_xdt.xr_ps.query(query='start_frequency > 100e9 AND end_frequency < 200e9')
262
278
  """
263
279
 
264
280
  if self._xdt.attrs.get("type") not in PS_DATASET_TYPES:
@@ -345,10 +361,6 @@ class ProcessingSetXdt:
345
361
 
346
362
  combined_field_and_source_xds = xr.Dataset()
347
363
  for ms_name, ms_xdt in self._xdt.items():
348
- correlated_data_name = ms_xdt.attrs["data_groups"][data_group][
349
- "correlated_data"
350
- ]
351
-
352
364
  field_and_source_xds = ms_xdt.xr_ms.get_field_and_source_xds(data_group)
353
365
 
354
366
  if not field_and_source_xds.attrs["type"] == "field_and_source_ephemeris":
@@ -369,38 +381,39 @@ class ProcessingSetXdt:
369
381
  combined_field_and_source_xds = xr.concat(
370
382
  [combined_field_and_source_xds, field_and_source_xds],
371
383
  dim="field_name",
384
+ join="outer",
372
385
  )
373
386
 
374
387
  if (len(combined_field_and_source_xds.data_vars) > 0) and (
375
- "FIELD_PHASE_CENTER" in combined_field_and_source_xds
388
+ "FIELD_PHASE_CENTER_DIRECTION" in combined_field_and_source_xds
376
389
  ):
377
390
  combined_field_and_source_xds = (
378
391
  combined_field_and_source_xds.drop_duplicates("field_name")
379
392
  )
380
393
 
381
- combined_field_and_source_xds["MEAN_PHASE_CENTER"] = (
382
- combined_field_and_source_xds["FIELD_PHASE_CENTER"].mean(
394
+ combined_field_and_source_xds["MEAN_PHASE_CENTER_DIRECTION"] = (
395
+ combined_field_and_source_xds["FIELD_PHASE_CENTER_DIRECTION"].mean(
383
396
  dim=["field_name"]
384
397
  )
385
398
  )
386
399
 
387
400
  ra1 = (
388
- combined_field_and_source_xds["FIELD_PHASE_CENTER"]
401
+ combined_field_and_source_xds["FIELD_PHASE_CENTER_DIRECTION"]
389
402
  .sel(sky_dir_label="ra")
390
403
  .values
391
404
  )
392
405
  dec1 = (
393
- combined_field_and_source_xds["FIELD_PHASE_CENTER"]
406
+ combined_field_and_source_xds["FIELD_PHASE_CENTER_DIRECTION"]
394
407
  .sel(sky_dir_label="dec")
395
408
  .values
396
409
  )
397
410
  ra2 = (
398
- combined_field_and_source_xds["MEAN_PHASE_CENTER"]
411
+ combined_field_and_source_xds["MEAN_PHASE_CENTER_DIRECTION"]
399
412
  .sel(sky_dir_label="ra")
400
413
  .values
401
414
  )
402
415
  dec2 = (
403
- combined_field_and_source_xds["MEAN_PHASE_CENTER"]
416
+ combined_field_and_source_xds["MEAN_PHASE_CENTER_DIRECTION"]
404
417
  .sel(sky_dir_label="dec")
405
418
  .values
406
419
  )
@@ -445,11 +458,6 @@ class ProcessingSetXdt:
445
458
 
446
459
  combined_ephemeris_field_and_source_xds = xr.Dataset()
447
460
  for ms_name, ms_xdt in self._xdt.items():
448
-
449
- correlated_data_name = ms_xdt.attrs["data_groups"][data_group][
450
- "correlated_data"
451
- ]
452
-
453
461
  field_and_source_xds = field_and_source_xds = (
454
462
  ms_xdt.xr_ms.get_field_and_source_xds(data_group)
455
463
  )
@@ -466,7 +474,7 @@ class ProcessingSetXdt:
466
474
  del field_and_source_xds["line_name"]
467
475
  del field_and_source_xds["line_label"]
468
476
 
469
- from xradio.measurement_set._utils._msv2.msv4_sub_xdss import (
477
+ from xradio.measurement_set._utils._utils.interpolate import (
470
478
  interpolate_to_time,
471
479
  )
472
480
 
@@ -494,24 +502,27 @@ class ProcessingSetXdt:
494
502
  combined_ephemeris_field_and_source_xds = xr.concat(
495
503
  [combined_ephemeris_field_and_source_xds, field_and_source_xds],
496
504
  dim="time",
505
+ join="outer",
497
506
  )
498
507
 
499
508
  if (len(combined_ephemeris_field_and_source_xds.data_vars) > 0) and (
500
- "FIELD_PHASE_CENTER" in combined_ephemeris_field_and_source_xds
509
+ "FIELD_PHASE_CENTER_DIRECTION" in combined_ephemeris_field_and_source_xds
501
510
  ):
502
511
 
503
512
  from xradio._utils.coord_math import wrap_to_pi
504
513
 
505
514
  offset = (
506
- combined_ephemeris_field_and_source_xds["FIELD_PHASE_CENTER"]
507
- - combined_ephemeris_field_and_source_xds["SOURCE_LOCATION"]
515
+ combined_ephemeris_field_and_source_xds["FIELD_PHASE_CENTER_DIRECTION"]
516
+ - combined_ephemeris_field_and_source_xds["SOURCE_DIRECTION"]
508
517
  )
509
518
  combined_ephemeris_field_and_source_xds["FIELD_OFFSET"] = xr.DataArray(
510
- wrap_to_pi(offset.sel(sky_pos_label=["ra", "dec"])).values,
519
+ wrap_to_pi(offset.sel(sky_dir_label=["ra", "dec"])).values,
511
520
  dims=["time", "sky_dir_label"],
512
521
  )
513
522
  combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].attrs = (
514
- combined_ephemeris_field_and_source_xds["FIELD_PHASE_CENTER"].attrs
523
+ combined_ephemeris_field_and_source_xds[
524
+ "FIELD_PHASE_CENTER_DIRECTION"
525
+ ].attrs
515
526
  )
516
527
  combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].attrs["units"] = (
517
528
  combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].attrs["units"][
@@ -594,15 +605,15 @@ class ProcessingSetXdt:
594
605
  from matplotlib import pyplot as plt
595
606
 
596
607
  if (len(combined_field_and_source_xds.data_vars) > 0) and (
597
- "FIELD_PHASE_CENTER" in combined_field_and_source_xds
608
+ "FIELD_PHASE_CENTER_DIRECTION" in combined_field_and_source_xds
598
609
  ):
599
610
  fig = plt.figure()
600
611
  plt.title("Field Phase Center Locations")
601
612
  scatter = plt.scatter(
602
- combined_field_and_source_xds["FIELD_PHASE_CENTER"].sel(
613
+ combined_field_and_source_xds["FIELD_PHASE_CENTER_DIRECTION"].sel(
603
614
  sky_dir_label="ra"
604
615
  ),
605
- combined_field_and_source_xds["FIELD_PHASE_CENTER"].sel(
616
+ combined_field_and_source_xds["FIELD_PHASE_CENTER_DIRECTION"].sel(
606
617
  sky_dir_label="dec"
607
618
  ),
608
619
  )
@@ -620,8 +631,8 @@ class ProcessingSetXdt:
620
631
  center_label = center_field_name
621
632
 
622
633
  plt.scatter(
623
- center_field["FIELD_PHASE_CENTER"].sel(sky_dir_label="ra"),
624
- center_field["FIELD_PHASE_CENTER"].sel(sky_dir_label="dec"),
634
+ center_field["FIELD_PHASE_CENTER_DIRECTION"].sel(sky_dir_label="ra"),
635
+ center_field["FIELD_PHASE_CENTER_DIRECTION"].sel(sky_dir_label="dec"),
625
636
  color="red",
626
637
  label=center_label,
627
638
  )
@@ -632,7 +643,7 @@ class ProcessingSetXdt:
632
643
  plt.show()
633
644
 
634
645
  if (len(combined_ephemeris_field_and_source_xds.data_vars) > 0) and (
635
- "FIELD_PHASE_CENTER" in combined_ephemeris_field_and_source_xds
646
+ "FIELD_PHASE_CENTER_DIRECTION" in combined_ephemeris_field_and_source_xds
636
647
  ):
637
648
 
638
649
  fig = plt.figure()
@@ -714,6 +725,7 @@ class ProcessingSetXdt:
714
725
  dim="antenna_name",
715
726
  data_vars="minimal",
716
727
  coords="minimal",
728
+ join="outer",
717
729
  )
718
730
 
719
731
  # ALMA WVR antenna_xds data has a NaN value for the antenna receptor angle.
@@ -805,7 +817,6 @@ class ProcessingSetXdt:
805
817
  """
806
818
  Creates annotations for when label_all_antennas=True
807
819
  """
808
- antenna_annotations = []
809
820
  for axis in antenna_axes:
810
821
  scatter = scatter_map[axis]
811
822
  coord_x, coord_y = np.array(scatter.get_offsets()).transpose()
@@ -814,7 +825,7 @@ class ProcessingSetXdt:
814
825
  for idx, (x, y) in enumerate(
815
826
  zip(coord_x + offset_x, coord_y + offset_y)
816
827
  ):
817
- annotation = axis.annotate(
828
+ axis.annotate(
818
829
  antenna_names[idx],
819
830
  (x, y),
820
831
  alpha=1,
@@ -867,801 +878,3 @@ class ProcessingSetXdt:
867
878
  fig.canvas.mpl_connect("motion_notify_event", antenna_hover)
868
879
 
869
880
  plt.show()
870
-
871
-
872
- # class ProcessingSet(dict):
873
- # """
874
- # A dictionary subclass representing a Processing Set (PS) containing Measurement Sets v4 (MS).
875
-
876
- # This class extends the built-in `dict` class to provide additional methods for
877
- # manipulating and selecting subsets of the Processing Set. It includes functionality
878
- # for summarizing metadata, selecting subsets based on various criteria, and
879
- # exporting the data to storage formats.
880
-
881
- # Parameters
882
- # ----------
883
- # *args : dict, optional
884
- # Variable length argument list passed to the base `dict` class.
885
- # **kwargs : dict, optional
886
- # Arbitrary keyword arguments passed to the base `dict` class.
887
- # """
888
-
889
- # def __init__(self, *args, **kwargs):
890
- # """
891
- # Initialize the ProcessingSet instance.
892
-
893
- # Parameters
894
- # ----------
895
- # *args : dict, optional
896
- # Variable length argument list passed to the base `dict` class.
897
- # **kwargs : dict, optional
898
- # Arbitrary keyword arguments passed to the base `dict` class.
899
- # """
900
- # super().__init__(*args, **kwargs)
901
- # self.meta = {"summary": {}}
902
-
903
- # def summary(self, data_group="base"):
904
- # """
905
- # Generate and retrieve a summary of the Processing Set.
906
-
907
- # The summary includes information such as the names of the Measurement Sets,
908
- # their intents, polarizations, spectral window names, field names, source names,
909
- # field coordinates, start frequencies, and end frequencies.
910
-
911
- # Parameters
912
- # ----------
913
- # data_group : str, optional
914
- # The data group to summarize. Default is "base".
915
-
916
- # Returns
917
- # -------
918
- # pandas.DataFrame
919
- # A DataFrame containing the summary information of the specified data group.
920
- # """
921
-
922
- # if data_group in self.meta["summary"]:
923
- # return self.meta["summary"][data_group]
924
- # else:
925
- # self.meta["summary"][data_group] = self._summary(data_group).sort_values(
926
- # by=["name"], ascending=True
927
- # )
928
- # return self.meta["summary"][data_group]
929
-
930
- # def get_ps_max_dims(self):
931
- # """
932
- # Determine the maximum dimensions across all Measurement Sets in the Processing Set.
933
-
934
- # This method examines each Measurement Set's dimensions and computes the maximum
935
- # size for each dimension across the entire Processing Set.
936
-
937
- # For example, if the Processing Set contains two MSs with dimensions (50, 20, 30) and (10, 30, 40),
938
- # the maximum dimensions will be (50, 30, 40).
939
-
940
- # Returns
941
- # -------
942
- # dict
943
- # A dictionary containing the maximum dimensions of the Processing Set, with dimension names as keys
944
- # and their maximum sizes as values.
945
- # """
946
- # if "max_dims" in self.meta:
947
- # return self.meta["max_dims"]
948
- # else:
949
- # self.meta["max_dims"] = self._get_ps_max_dims()
950
- # return self.meta["max_dims"]
951
-
952
- # def get_ps_freq_axis(self):
953
- # """
954
- # Combine the frequency axes of all Measurement Sets in the Processing Set.
955
-
956
- # This method aggregates the frequency information from each Measurement Set to create
957
- # a unified frequency axis for the entire Processing Set.
958
-
959
- # Returns
960
- # -------
961
- # xarray.DataArray
962
- # The combined frequency axis of the Processing Set.
963
- # """
964
- # if "freq_axis" in self.meta:
965
- # return self.meta["freq_axis"]
966
- # else:
967
- # self.meta["freq_axis"] = self._get_ps_freq_axis()
968
- # return self.meta["freq_axis"]
969
-
970
- # def _summary(self, data_group="base"):
971
- # summary_data = {
972
- # "name": [],
973
- # "intents": [],
974
- # "shape": [],
975
- # "polarization": [],
976
- # "scan_name": [],
977
- # "spw_name": [],
978
- # "field_name": [],
979
- # "source_name": [],
980
- # "line_name": [],
981
- # "field_coords": [],
982
- # "start_frequency": [],
983
- # "end_frequency": [],
984
- # }
985
- # from astropy.coordinates import SkyCoord
986
- # import astropy.units as u
987
-
988
- # for key, value in self.items():
989
- # summary_data["name"].append(key)
990
- # summary_data["intents"].append(partition_info["intents"])
991
- # summary_data["spw_name"].append(
992
- # partition_info["spectral_window_name"]
993
- # )
994
- # summary_data["polarization"].append(value.polarization.values)
995
- # summary_data["scan_name"].append(partition_info["scan_name"])
996
- # data_name = value.attrs["data_groups"][data_group]["correlated_data"]
997
-
998
- # if "VISIBILITY" in data_name:
999
- # center_name = "FIELD_PHASE_CENTER"
1000
-
1001
- # if "SPECTRUM" in data_name:
1002
- # center_name = "FIELD_REFERENCE_CENTER"
1003
-
1004
- # summary_data["shape"].append(value[data_name].shape)
1005
-
1006
- # summary_data["field_name"].append(
1007
- # partition_info["field_name"]
1008
- # )
1009
- # summary_data["source_name"].append(
1010
- # partition_info["source_name"]
1011
- # )
1012
-
1013
- # summary_data["line_name"].append(partition_info["line_name"])
1014
-
1015
- # summary_data["start_frequency"].append(
1016
- # to_list(value["frequency"].values)[0]
1017
- # )
1018
- # summary_data["end_frequency"].append(to_list(value["frequency"].values)[-1])
1019
-
1020
- # if (
1021
- # value[data_name].attrs["field_and_source_xds"].attrs["type"]
1022
- # == "field_and_source_ephemeris"
1023
- # ):
1024
- # summary_data["field_coords"].append("Ephemeris")
1025
- # # elif (
1026
- # # "time"
1027
- # # in value[data_name].attrs["field_and_source_xds"][center_name].coords
1028
- # # ):
1029
- # elif (
1030
- # value[data_name]
1031
- # .attrs["field_and_source_xds"][center_name]["field_name"]
1032
- # .size
1033
- # > 1
1034
- # ):
1035
- # summary_data["field_coords"].append("Multi-Phase-Center")
1036
- # else:
1037
- # ra_dec_rad = (
1038
- # value[data_name]
1039
- # .attrs["field_and_source_xds"][center_name]
1040
- # .values[0, :]
1041
- # )
1042
- # frame = (
1043
- # value[data_name]
1044
- # .attrs["field_and_source_xds"][center_name]
1045
- # .attrs["frame"]
1046
- # .lower()
1047
- # )
1048
-
1049
- # coord = SkyCoord(
1050
- # ra=ra_dec_rad[0] * u.rad, dec=ra_dec_rad[1] * u.rad, frame=frame
1051
- # )
1052
-
1053
- # summary_data["field_coords"].append(
1054
- # [
1055
- # frame,
1056
- # coord.ra.to_string(unit=u.hour, precision=2),
1057
- # coord.dec.to_string(unit=u.deg, precision=2),
1058
- # ]
1059
- # )
1060
-
1061
- # summary_df = pd.DataFrame(summary_data)
1062
- # return summary_df
1063
-
1064
- # def _get_ps_freq_axis(self):
1065
-
1066
- # spw_ids = []
1067
- # freq_axis_list = []
1068
- # frame = self.get(0).frequency.attrs["observer"]
1069
- # for ms_xds in self.values():
1070
- # assert (
1071
- # frame == ms_xds.frequency.attrs["observer"]
1072
- # ), "Frequency reference frame not consistent in Processing Set."
1073
- # if ms_xds.frequency.attrs["spectral_window_id"] not in spw_ids:
1074
- # spw_ids.append(ms_xds.frequency.attrs["spectral_window_id"])
1075
- # freq_axis_list.append(ms_xds.frequency)
1076
-
1077
- # freq_axis = xr.concat(freq_axis_list, dim="frequency").sortby("frequency")
1078
- # return freq_axis
1079
-
1080
- # def _get_ps_max_dims(self):
1081
- # max_dims = None
1082
- # for ms_xds in self.values():
1083
- # if max_dims is None:
1084
- # max_dims = dict(ms_xds.sizes)
1085
- # else:
1086
- # for dim_name, size in ms_xds.sizes.items():
1087
- # if dim_name in max_dims:
1088
- # if max_dims[dim_name] < size:
1089
- # max_dims[dim_name] = size
1090
- # else:
1091
- # max_dims[dim_name] = size
1092
- # return max_dims
1093
-
1094
- # def get(self, id):
1095
- # return self[list(self.keys())[id]]
1096
-
1097
- # def sel(self, string_exact_match: bool = True, query: str = None, **kwargs):
1098
- # """
1099
- # Select a subset of the Processing Set based on specified criteria.
1100
-
1101
- # This method allows filtering the Processing Set by matching column names and values
1102
- # or by applying a Pandas query string. The selection criteria can target various
1103
- # attributes of the Measurement Sets such as intents, polarization, spectral window names, etc.
1104
-
1105
- # Note
1106
- # ----
1107
- # This selection does not modify the actual data within the Measurement Sets. For example, if
1108
- # a Measurement Set has `field_name=['field_0','field_10','field_08']` and `ps.query(field_name='field_0')`
1109
- # is invoked, the resulting subset will still contain the original list `['field_0','field_10','field_08']`.
1110
-
1111
- # Parameters
1112
- # ----------
1113
- # string_exact_match : bool, optional
1114
- # If `True`, string matching will require exact matches for string and string list columns.
1115
- # If `False`, partial matches are allowed. Default is `True`.
1116
- # query : str, optional
1117
- # A Pandas query string to apply additional filtering. Default is `None`.
1118
- # **kwargs : dict
1119
- # Keyword arguments representing column names and their corresponding values to filter the Processing Set.
1120
-
1121
- # Returns
1122
- # -------
1123
- # ProcessingSet
1124
- # A new `ProcessingSet` instance containing only the Measurement Sets that match the selection criteria.
1125
-
1126
- # Examples
1127
- # --------
1128
- # >>> # Select all MSs with intents 'OBSERVE_TARGET#ON_SOURCE' and polarization 'RR' or 'LL'
1129
- # >>> selected_ps = ps.query(intents='OBSERVE_TARGET#ON_SOURCE', polarization=['RR', 'LL'])
1130
-
1131
- # >>> # Select all MSs with start_frequency greater than 100 GHz and less than 200 GHz
1132
- # >>> selected_ps = ps.query(query='start_frequency > 100e9 AND end_frequency < 200e9')
1133
- # """
1134
- # import numpy as np
1135
-
1136
- # def select_rows(df, col, sel_vals, string_exact_match):
1137
- # def check_selection(row_val):
1138
- # row_val = to_list(
1139
- # row_val
1140
- # ) # make sure that it is a list so that we can iterate over it.
1141
-
1142
- # for rw in row_val:
1143
- # for s in sel_vals:
1144
- # if string_exact_match:
1145
- # if rw == s:
1146
- # return True
1147
- # else:
1148
- # if s in rw:
1149
- # return True
1150
- # return False
1151
-
1152
- # return df[df[col].apply(check_selection)]
1153
-
1154
- # summary_table = self.summary()
1155
- # for key, value in kwargs.items():
1156
- # value = to_list(value) # make sure value is a list.
1157
-
1158
- # if len(value) == 1 and isinstance(value[0], slice):
1159
- # summary_table = summary_table[
1160
- # summary_table[key].between(value[0].start, value[0].stop)
1161
- # ]
1162
- # else:
1163
- # summary_table = select_rows(
1164
- # summary_table, key, value, string_exact_match
1165
- # )
1166
-
1167
- # if query is not None:
1168
- # summary_table = summary_table.query(query)
1169
-
1170
- # sub_ps = ProcessingSet()
1171
- # for key, val in self.items():
1172
- # if key in summary_table["name"].values:
1173
- # sub_ps[key] = val
1174
-
1175
- # return sub_ps
1176
-
1177
- # def ms_sel(self, **kwargs):
1178
- # """
1179
- # Select a subset of the Processing Set by applying the `xarray.Dataset.sel` method to each Measurement Set.
1180
-
1181
- # This method allows for selection based on label-based indexing for each dimension of the datasets.
1182
-
1183
- # Parameters
1184
- # ----------
1185
- # **kwargs : dict
1186
- # Keyword arguments representing dimension names and the labels to select along those dimensions.
1187
- # These are passed directly to the `xarray.Dataset.sel <https://docs.xarray.dev/en/latest/generated/xarray.Dataset.sel.html>`__ method.
1188
-
1189
- # Returns
1190
- # -------
1191
- # ProcessingSet
1192
- # A new `ProcessingSet` instance containing the selected subsets of each Measurement Set.
1193
- # """
1194
- # sub_ps = ProcessingSet()
1195
- # for key, val in self.items():
1196
- # sub_ps[key] = val.sel(kwargs)
1197
- # return sub_ps
1198
-
1199
- # def ms_isel(self, **kwargs):
1200
- # """
1201
- # Select a subset of the Processing Set by applying the `isel` method to each Measurement Set.
1202
-
1203
- # This method allows for selection based on integer-based indexing for each dimension of the datasets.
1204
-
1205
- # Parameters
1206
- # ----------
1207
- # **kwargs : dict
1208
- # Keyword arguments representing dimension names and the integer indices to select along those dimensions.
1209
- # These are passed directly to the `xarray.Dataset.isel <https://docs.xarray.dev/en/latest/generated/xarray.Dataset.isel.html>`__ method.
1210
-
1211
- # Returns
1212
- # -------
1213
- # ProcessingSet
1214
- # A new `ProcessingSet` instance containing the selected subsets of each Measurement Set.
1215
- # """
1216
- # sub_ps = ProcessingSet()
1217
- # for key, val in self.items():
1218
- # sub_ps[key] = val.isel(kwargs)
1219
- # return sub_ps
1220
-
1221
- # def to_store(self, store, **kwargs):
1222
- # """
1223
- # Write the Processing Set to a Zarr store.
1224
-
1225
- # This method serializes each Measurement Set within the Processing Set to a separate Zarr group
1226
- # within the specified store directory. Note that writing to cloud storage is not supported yet.
1227
-
1228
- # Parameters
1229
- # ----------
1230
- # store : str
1231
- # The filesystem path to the Zarr store directory where the data will be saved.
1232
- # **kwargs : dict, optional
1233
- # Additional keyword arguments to be passed to the `xarray.Dataset.to_zarr` method.
1234
- # Refer to the `xarray.Dataset.to_zarr <https://docs.xarray.dev/en/latest/generated/xarray.Dataset.to_zarr.html>`__
1235
- # for available options.
1236
-
1237
- # Returns
1238
- # -------
1239
- # None
1240
-
1241
- # Raises
1242
- # ------
1243
- # OSError
1244
- # If the specified store path is invalid or not writable.
1245
-
1246
- # Examples
1247
- # --------
1248
- # >>> # Save the Processing Set to a local Zarr store
1249
- # >>> ps.to_store('/path/to/zarr_store')
1250
- # """
1251
- # import os
1252
-
1253
- # for key, value in self.items():
1254
- # value.to_store(os.path.join(store, key), **kwargs)
1255
-
1256
- # def get_combined_field_and_source_xds(self, data_group="base"):
1257
- # """
1258
- # Combine all non-ephemeris `field_and_source_xds` datasets from a Processing Set for a datagroup into a single dataset.
1259
-
1260
- # Parameters
1261
- # ----------
1262
- # data_group : str, optional
1263
- # The data group to process. Default is "base".
1264
-
1265
- # Returns
1266
- # -------
1267
- # xarray.Dataset
1268
- # combined_field_and_source_xds: Combined dataset for standard fields.
1269
-
1270
- # Raises
1271
- # ------
1272
- # ValueError
1273
- # If the `field_and_source_xds` attribute is missing or improperly formatted in any Measurement Set.
1274
- # """
1275
-
1276
- # combined_field_and_source_xds = xr.Dataset()
1277
- # for ms_name, ms_xds in self.items():
1278
- # correlated_data_name = ms_xds.attrs["data_groups"][data_group][
1279
- # "correlated_data"
1280
- # ]
1281
-
1282
- # field_and_source_xds = (
1283
- # ms_xds[correlated_data_name]
1284
- # .attrs["field_and_source_xds"]
1285
- # .copy(deep=True)
1286
- # )
1287
-
1288
- # if not field_and_source_xds.attrs["type"] == "field_and_source_ephemeris":
1289
-
1290
- # if (
1291
- # "line_name" in field_and_source_xds.coords
1292
- # ): # Not including line info since it is a function of spw.
1293
- # field_and_source_xds = field_and_source_xds.drop_vars(
1294
- # ["LINE_REST_FREQUENCY", "LINE_SYSTEMIC_VELOCITY"],
1295
- # errors="ignore",
1296
- # )
1297
- # del field_and_source_xds["line_name"]
1298
- # del field_and_source_xds["line_label"]
1299
-
1300
- # if len(combined_field_and_source_xds.data_vars) == 0:
1301
- # combined_field_and_source_xds = field_and_source_xds
1302
- # else:
1303
- # combined_field_and_source_xds = xr.concat(
1304
- # [combined_field_and_source_xds, field_and_source_xds],
1305
- # dim="field_name",
1306
- # )
1307
-
1308
- # if (len(combined_field_and_source_xds.data_vars) > 0) and (
1309
- # "FIELD_PHASE_CENTER" in combined_field_and_source_xds
1310
- # ):
1311
- # combined_field_and_source_xds = (
1312
- # combined_field_and_source_xds.drop_duplicates("field_name")
1313
- # )
1314
-
1315
- # combined_field_and_source_xds["MEAN_PHASE_CENTER"] = (
1316
- # combined_field_and_source_xds["FIELD_PHASE_CENTER"].mean(
1317
- # dim=["field_name"]
1318
- # )
1319
- # )
1320
-
1321
- # ra1 = (
1322
- # combined_field_and_source_xds["FIELD_PHASE_CENTER"]
1323
- # .sel(sky_dir_label="ra")
1324
- # .values
1325
- # )
1326
- # dec1 = (
1327
- # combined_field_and_source_xds["FIELD_PHASE_CENTER"]
1328
- # .sel(sky_dir_label="dec")
1329
- # .values
1330
- # )
1331
- # ra2 = (
1332
- # combined_field_and_source_xds["MEAN_PHASE_CENTER"]
1333
- # .sel(sky_dir_label="ra")
1334
- # .values
1335
- # )
1336
- # dec2 = (
1337
- # combined_field_and_source_xds["MEAN_PHASE_CENTER"]
1338
- # .sel(sky_dir_label="dec")
1339
- # .values
1340
- # )
1341
-
1342
- # from xradio._utils.coord_math import haversine
1343
-
1344
- # distance = haversine(ra1, dec1, ra2, dec2)
1345
- # min_index = distance.argmin()
1346
-
1347
- # combined_field_and_source_xds.attrs["center_field_name"] = (
1348
- # combined_field_and_source_xds.field_name[min_index].values
1349
- # )
1350
-
1351
- # return combined_field_and_source_xds
1352
-
1353
-
1354
- # def get_combined_field_and_source_xds_ephemeris(self, data_group="base"):
1355
- # """
1356
- # Combine all ephemeris `field_and_source_xds` datasets from a Processing Set for a datagroup into a single dataset.
1357
-
1358
- # Parameters
1359
- # ----------
1360
- # data_group : str, optional
1361
- # The data group to process. Default is "base".
1362
-
1363
- # Returns
1364
- # -------
1365
- # xarray.Dataset
1366
- # - combined_ephemeris_field_and_source_xds: Combined dataset for ephemeris fields.
1367
-
1368
- # Raises
1369
- # ------
1370
- # ValueError
1371
- # If the `field_and_source_xds` attribute is missing or improperly formatted in any Measurement Set.
1372
- # """
1373
-
1374
- # combined_ephemeris_field_and_source_xds = xr.Dataset()
1375
- # for ms_name, ms_xds in self.items():
1376
-
1377
- # correlated_data_name = ms_xds.attrs["data_groups"][data_group][
1378
- # "correlated_data"
1379
- # ]
1380
-
1381
- # field_and_source_xds = (
1382
- # ms_xds[correlated_data_name]
1383
- # .attrs["field_and_source_xds"]
1384
- # .copy(deep=True)
1385
- # )
1386
-
1387
- # if field_and_source_xds.attrs["type"] == "field_and_source_ephemeris":
1388
-
1389
- # if (
1390
- # "line_name" in field_and_source_xds.coords
1391
- # ): # Not including line info since it is a function of spw.
1392
- # field_and_source_xds = field_and_source_xds.drop_vars(
1393
- # ["LINE_REST_FREQUENCY", "LINE_SYSTEMIC_VELOCITY"],
1394
- # errors="ignore",
1395
- # )
1396
- # del field_and_source_xds["line_name"]
1397
- # del field_and_source_xds["line_label"]
1398
-
1399
- # from xradio.measurement_set._utils._msv2.msv4_sub_xdss import (
1400
- # interpolate_to_time,
1401
- # )
1402
-
1403
- # if "time_ephemeris" in field_and_source_xds:
1404
- # field_and_source_xds = interpolate_to_time(
1405
- # field_and_source_xds,
1406
- # field_and_source_xds.time,
1407
- # "field_and_source_xds",
1408
- # "time_ephemeris",
1409
- # )
1410
- # del field_and_source_xds["time_ephemeris"]
1411
- # field_and_source_xds = field_and_source_xds.rename(
1412
- # {"time_ephemeris": "time"}
1413
- # )
1414
-
1415
- # if "OBSERVER_POSITION" in field_and_source_xds:
1416
- # field_and_source_xds = field_and_source_xds.drop_vars(
1417
- # ["OBSERVER_POSITION"], errors="ignore"
1418
- # )
1419
-
1420
- # if len(combined_ephemeris_field_and_source_xds.data_vars) == 0:
1421
- # combined_ephemeris_field_and_source_xds = field_and_source_xds
1422
- # else:
1423
-
1424
- # combined_ephemeris_field_and_source_xds = xr.concat(
1425
- # [combined_ephemeris_field_and_source_xds, field_and_source_xds],
1426
- # dim="time",
1427
- # )
1428
-
1429
- # if (len(combined_ephemeris_field_and_source_xds.data_vars) > 0) and (
1430
- # "FIELD_PHASE_CENTER" in combined_ephemeris_field_and_source_xds
1431
- # ):
1432
-
1433
- # from xradio._utils.coord_math import wrap_to_pi
1434
-
1435
- # offset = (
1436
- # combined_ephemeris_field_and_source_xds["FIELD_PHASE_CENTER"]
1437
- # - combined_ephemeris_field_and_source_xds["SOURCE_LOCATION"]
1438
- # )
1439
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"] = xr.DataArray(
1440
- # wrap_to_pi(offset.sel(sky_pos_label=["ra", "dec"])).values,
1441
- # dims=["time", "sky_dir_label"],
1442
- # )
1443
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].attrs = (
1444
- # combined_ephemeris_field_and_source_xds["FIELD_PHASE_CENTER"].attrs
1445
- # )
1446
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].attrs["units"] = (
1447
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].attrs["units"][
1448
- # :2
1449
- # ]
1450
- # )
1451
-
1452
- # ra1 = (
1453
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"]
1454
- # .sel(sky_dir_label="ra")
1455
- # .values
1456
- # )
1457
- # dec1 = (
1458
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"]
1459
- # .sel(sky_dir_label="dec")
1460
- # .values
1461
- # )
1462
- # ra2 = 0.0
1463
- # dec2 = 0.0
1464
-
1465
- # from xradio._utils.coord_math import haversine
1466
-
1467
- # distance = haversine(ra1, dec1, ra2, dec2)
1468
- # min_index = distance.argmin()
1469
-
1470
- # combined_ephemeris_field_and_source_xds.attrs["center_field_name"] = (
1471
- # combined_ephemeris_field_and_source_xds.field_name[min_index].values
1472
- # )
1473
-
1474
- # return combined_ephemeris_field_and_source_xds
1475
-
1476
- # def plot_phase_centers(self, label_all_fields=False, data_group="base"):
1477
- # """
1478
- # Plot the phase center locations of all fields in the Processing Set.
1479
-
1480
- # This method is primarily used for visualizing mosaics. It generates scatter plots of
1481
- # the phase center coordinates for both standard and ephemeris fields. The central field
1482
- # is highlighted in red based on the closest phase center calculation.
1483
-
1484
- # Parameters
1485
- # ----------
1486
- # label_all_fields : bool, optional
1487
- # If `True`, all fields will be labeled on the plot. Default is `False`.
1488
- # data_group : str, optional
1489
- # The data group to use for processing. Default is "base".
1490
-
1491
- # Returns
1492
- # -------
1493
- # None
1494
-
1495
- # Raises
1496
- # ------
1497
- # ValueError
1498
- # If the combined datasets are empty or improperly formatted.
1499
- # """
1500
- # combined_field_and_source_xds = self.get_combined_field_and_source_xds(
1501
- # data_group
1502
- # )
1503
- # combined_ephemeris_field_and_source_xds = (
1504
- # self.get_combined_field_and_source_xds_ephemeris(data_group)
1505
- # )
1506
- # from matplotlib import pyplot as plt
1507
-
1508
- # if (len(combined_field_and_source_xds.data_vars) > 0) and (
1509
- # "FIELD_PHASE_CENTER" in combined_field_and_source_xds
1510
- # ):
1511
- # plt.figure()
1512
- # plt.title("Field Phase Center Locations")
1513
- # plt.scatter(
1514
- # combined_field_and_source_xds["FIELD_PHASE_CENTER"].sel(
1515
- # sky_dir_label="ra"
1516
- # ),
1517
- # combined_field_and_source_xds["FIELD_PHASE_CENTER"].sel(
1518
- # sky_dir_label="dec"
1519
- # ),
1520
- # )
1521
-
1522
- # center_field_name = combined_field_and_source_xds.attrs["center_field_name"]
1523
- # center_field = combined_field_and_source_xds.sel(
1524
- # field_name=center_field_name
1525
- # )
1526
- # plt.scatter(
1527
- # center_field["FIELD_PHASE_CENTER"].sel(sky_dir_label="ra"),
1528
- # center_field["FIELD_PHASE_CENTER"].sel(sky_dir_label="dec"),
1529
- # color="red",
1530
- # label=center_field_name,
1531
- # )
1532
- # plt.xlabel("RA (rad)")
1533
- # plt.ylabel("DEC (rad)")
1534
- # plt.legend()
1535
- # plt.show()
1536
-
1537
- # if (len(combined_ephemeris_field_and_source_xds.data_vars) > 0) and (
1538
- # "FIELD_PHASE_CENTER" in combined_ephemeris_field_and_source_xds
1539
- # ):
1540
-
1541
- # plt.figure()
1542
- # plt.title(
1543
- # "Offset of Field Phase Center from Source Location (Ephemeris Data)"
1544
- # )
1545
- # plt.scatter(
1546
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].sel(
1547
- # sky_dir_label="ra"
1548
- # ),
1549
- # combined_ephemeris_field_and_source_xds["FIELD_OFFSET"].sel(
1550
- # sky_dir_label="dec"
1551
- # ),
1552
- # )
1553
-
1554
- # center_field_name = combined_ephemeris_field_and_source_xds.attrs[
1555
- # "center_field_name"
1556
- # ]
1557
-
1558
- # combined_ephemeris_field_and_source_xds = (
1559
- # combined_ephemeris_field_and_source_xds.set_xindex("field_name")
1560
- # )
1561
-
1562
- # center_field = combined_ephemeris_field_and_source_xds.sel(
1563
- # field_name=center_field_name
1564
- # )
1565
- # plt.scatter(
1566
- # center_field["FIELD_OFFSET"].sel(sky_dir_label="ra"),
1567
- # center_field["FIELD_OFFSET"].sel(sky_dir_label="dec"),
1568
- # color="red",
1569
- # label=center_field_name,
1570
- # )
1571
- # plt.xlabel("RA Offset (rad)")
1572
- # plt.ylabel("DEC Offset (rad)")
1573
- # plt.legend()
1574
- # plt.show()
1575
-
1576
- # def get_combined_antenna_xds(self):
1577
- # """
1578
- # Combine the `antenna_xds` datasets from all Measurement Sets into a single dataset.
1579
-
1580
- # This method concatenates the antenna datasets from each Measurement Set along the 'antenna_name' dimension.
1581
-
1582
- # Returns
1583
- # -------
1584
- # xarray.Dataset
1585
- # A combined `xarray.Dataset` containing antenna information from all Measurement Sets.
1586
-
1587
- # Raises
1588
- # ------
1589
- # ValueError
1590
- # If antenna datasets are missing required variables or improperly formatted.
1591
- # """
1592
- # combined_antenna_xds = xr.Dataset()
1593
- # for cor_name, ms_xds in self.items():
1594
- # antenna_xds = ms_xds.antenna_xds.copy(deep=True)
1595
-
1596
- # if len(combined_antenna_xds.data_vars) == 0:
1597
- # combined_antenna_xds = antenna_xds
1598
- # else:
1599
- # combined_antenna_xds = xr.concat(
1600
- # [combined_antenna_xds, antenna_xds],
1601
- # dim="antenna_name",
1602
- # data_vars="minimal",
1603
- # coords="minimal",
1604
- # )
1605
-
1606
- # # ALMA WVR antenna_xds data has a NaN value for the antenna receptor angle.
1607
- # if "ANTENNA_RECEPTOR_ANGLE" in combined_antenna_xds.data_vars:
1608
- # combined_antenna_xds = combined_antenna_xds.dropna("antenna_name")
1609
-
1610
- # combined_antenna_xds = combined_antenna_xds.drop_duplicates("antenna_name")
1611
-
1612
- # return combined_antenna_xds
1613
-
1614
- # def plot_antenna_positions(self):
1615
- # """
1616
- # Plot the antenna positions of all antennas in the Processing Set.
1617
-
1618
- # This method generates three scatter plots displaying the antenna positions in different planes:
1619
- # - X vs Y
1620
- # - X vs Z
1621
- # - Y vs Z
1622
-
1623
- # Parameters
1624
- # ----------
1625
- # None
1626
-
1627
- # Returns
1628
- # -------
1629
- # None
1630
-
1631
- # Raises
1632
- # ------
1633
- # ValueError
1634
- # If the combined antenna dataset is empty or missing required coordinates.
1635
- # """
1636
- # combined_antenna_xds = self.get_combined_antenna_xds()
1637
- # from matplotlib import pyplot as plt
1638
-
1639
- # plt.figure()
1640
- # plt.title("Antenna Positions")
1641
- # plt.scatter(
1642
- # combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="x"),
1643
- # combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="y"),
1644
- # )
1645
- # plt.xlabel("x (m)")
1646
- # plt.ylabel("y (m)")
1647
- # plt.show()
1648
-
1649
- # plt.figure()
1650
- # plt.title("Antenna Positions")
1651
- # plt.scatter(
1652
- # combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="x"),
1653
- # combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="z"),
1654
- # )
1655
- # plt.xlabel("x (m)")
1656
- # plt.ylabel("z (m)")
1657
- # plt.show()
1658
-
1659
- # plt.figure()
1660
- # plt.title("Antenna Positions")
1661
- # plt.scatter(
1662
- # combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="y"),
1663
- # combined_antenna_xds["ANTENNA_POSITION"].sel(cartesian_pos_label="z"),
1664
- # )
1665
- # plt.xlabel("y (m)")
1666
- # plt.ylabel("z (m)")
1667
- # plt.show()