cubevis 0.5.14__py3-none-any.whl → 0.5.16__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.
Potentially problematic release.
This version of cubevis might be problematic. Click here for more details.
- cubevis/__version__.py +1 -1
- cubevis/private/apps/__init__.py +5 -1
- cubevis/private/apps/_createmask.py +6 -6
- cubevis/private/apps/_createregion.py +5 -5
- {cubevis-0.5.14.dist-info → cubevis-0.5.16.dist-info}/METADATA +1 -1
- {cubevis-0.5.14.dist-info → cubevis-0.5.16.dist-info}/RECORD +8 -28
- cubevis/data/measurement_set/__init__.py +0 -7
- cubevis/data/measurement_set/_ms_data.py +0 -178
- cubevis/data/measurement_set/processing_set/__init__.py +0 -30
- cubevis/data/measurement_set/processing_set/_ps_concat.py +0 -98
- cubevis/data/measurement_set/processing_set/_ps_coords.py +0 -78
- cubevis/data/measurement_set/processing_set/_ps_data.py +0 -213
- cubevis/data/measurement_set/processing_set/_ps_io.py +0 -55
- cubevis/data/measurement_set/processing_set/_ps_raster_data.py +0 -154
- cubevis/data/measurement_set/processing_set/_ps_select.py +0 -91
- cubevis/data/measurement_set/processing_set/_ps_stats.py +0 -218
- cubevis/data/measurement_set/processing_set/_xds_data.py +0 -149
- cubevis/plot/__init__.py +0 -1
- cubevis/plot/ms_plot/__init__.py +0 -29
- cubevis/plot/ms_plot/_ms_plot.py +0 -242
- cubevis/plot/ms_plot/_ms_plot_constants.py +0 -22
- cubevis/plot/ms_plot/_ms_plot_selectors.py +0 -348
- cubevis/plot/ms_plot/_raster_plot.py +0 -292
- cubevis/plot/ms_plot/_raster_plot_inputs.py +0 -116
- cubevis/plot/ms_plot/_xds_plot_axes.py +0 -110
- cubevis/private/apps/_ms_raster.py +0 -815
- {cubevis-0.5.14.dist-info → cubevis-0.5.16.dist-info}/WHEEL +0 -0
- {cubevis-0.5.14.dist-info → cubevis-0.5.16.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
MeasurementSet data backend using xradio Processing Set.
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
import pandas as pd
|
|
7
|
-
|
|
8
|
-
try:
|
|
9
|
-
from cubevis.data.measurement_set.processing_set._ps_io import get_processing_set
|
|
10
|
-
_HAVE_XRADIO = True
|
|
11
|
-
from cubevis.data.measurement_set.processing_set._ps_select import select_ps
|
|
12
|
-
from cubevis.data.measurement_set.processing_set._ps_stats import calculate_ps_stats
|
|
13
|
-
from cubevis.data.measurement_set.processing_set._ps_raster_data import raster_data
|
|
14
|
-
from cubevis.data.measurement_set.processing_set._xds_data import get_correlated_data
|
|
15
|
-
except ImportError as e:
|
|
16
|
-
_HAVE_XRADIO = False
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class PsData:
|
|
20
|
-
'''
|
|
21
|
-
Class implementing data backend using xradio Processing Set for accessing and selecting MeasurementSet data.
|
|
22
|
-
'''
|
|
23
|
-
|
|
24
|
-
def __init__(self, ms, logger):
|
|
25
|
-
if not _HAVE_XRADIO:
|
|
26
|
-
raise RuntimeError("xradio package not available for reading MeasurementSet")
|
|
27
|
-
|
|
28
|
-
if not ms:
|
|
29
|
-
raise RuntimeError("MS path not available for reading MeasurementSet")
|
|
30
|
-
|
|
31
|
-
# Open processing set from zarr
|
|
32
|
-
# Converts msv2 if ms path is not zarr
|
|
33
|
-
self._ps_xdt, self._zarr_path = get_processing_set(ms, logger)
|
|
34
|
-
|
|
35
|
-
self._logger = logger
|
|
36
|
-
self._selection = {}
|
|
37
|
-
self._selected_ps_xdt = None # cumulative selection
|
|
38
|
-
|
|
39
|
-
def get_path(self):
|
|
40
|
-
''' Return path to zarr file (input or converted from msv2) '''
|
|
41
|
-
return self._zarr_path
|
|
42
|
-
|
|
43
|
-
def summary(self, data_group='base', columns=None):
|
|
44
|
-
''' Print full or selected summary of Processing Set metadata, optionally by ms '''
|
|
45
|
-
ps_summary = self._ps_xdt.xr_ps.summary(data_group=data_group)
|
|
46
|
-
pd.set_option("display.max_rows", len(self._ps_xdt))
|
|
47
|
-
pd.set_option("display.max_columns", len(ps_summary.columns))
|
|
48
|
-
pd.set_option("display.max_colwidth", None)
|
|
49
|
-
|
|
50
|
-
if columns is None:
|
|
51
|
-
print(ps_summary)
|
|
52
|
-
elif columns == "by_ms":
|
|
53
|
-
for row in ps_summary.itertuples(index=False):
|
|
54
|
-
print(f"MSv4 name: {row[0]}")
|
|
55
|
-
print(f"intent: {row[1]}")
|
|
56
|
-
shape = row[2]
|
|
57
|
-
print(f"shape: {shape[0]} times, {shape[1]} baselines, {shape[2]} channels, {shape[3]} polarizations")
|
|
58
|
-
print(f"polarization: {row[3]}")
|
|
59
|
-
scans = [str(scan) for scan in row[4]]
|
|
60
|
-
print(f"scan_name: {scans}")
|
|
61
|
-
print(f"spw_name: {row[5]}")
|
|
62
|
-
fields = [str(field) for field in row[6]]
|
|
63
|
-
print(f"field_name: {fields}")
|
|
64
|
-
sources = [str(source) for source in row[7]]
|
|
65
|
-
print(f"source_name: {sources}")
|
|
66
|
-
lines = [str(line) for line in row[8]]
|
|
67
|
-
print(f"line_name: {lines}")
|
|
68
|
-
field_coords = row[9]
|
|
69
|
-
print(f"field_coords: ({field_coords[0]}) {field_coords[1]} {field_coords[2]}")
|
|
70
|
-
print(f"frequency range: {row[10]:e} - {row[11]:e}")
|
|
71
|
-
print("-----")
|
|
72
|
-
else:
|
|
73
|
-
if isinstance(columns, str):
|
|
74
|
-
columns = [columns]
|
|
75
|
-
col_df = ps_summary[columns]
|
|
76
|
-
print(col_df)
|
|
77
|
-
|
|
78
|
-
def get_summary(self):
|
|
79
|
-
''' Return summary of original ps '''
|
|
80
|
-
return self._ps_xdt.xr_ps.summary()
|
|
81
|
-
|
|
82
|
-
def get_data_groups(self):
|
|
83
|
-
''' Returns set of data group names in Processing Set data. '''
|
|
84
|
-
data_groups = []
|
|
85
|
-
for ms_xdt_name in self._ps_xdt:
|
|
86
|
-
data_groups.extend(list(self._ps_xdt[ms_xdt_name].data_groups))
|
|
87
|
-
return set(data_groups)
|
|
88
|
-
|
|
89
|
-
def get_antennas(self, plot_positions=False, label_antennas=False):
|
|
90
|
-
''' Returns list of antenna names in ProcessingSet antenna_xds.
|
|
91
|
-
plot_positions (bool): show plot of antenna positions.
|
|
92
|
-
label_antennas (bool): label positions with antenna names.
|
|
93
|
-
'''
|
|
94
|
-
if plot_positions:
|
|
95
|
-
self._ps_xdt.xr_ps.plot_antenna_positions(label_antennas)
|
|
96
|
-
return self._ps_xdt.xr_ps.get_combined_antenna_xds().antenna_name.values.tolist()
|
|
97
|
-
|
|
98
|
-
def plot_phase_centers(self, label_all_fields=False, data_group='base'):
|
|
99
|
-
''' Plot the phase center locations of all fields in the Processing Set (original or selected) and label central field.
|
|
100
|
-
label_all_fields (bool); label all fields on the plot
|
|
101
|
-
data_group (str); data group to use for processing.
|
|
102
|
-
'''
|
|
103
|
-
self._ps_xdt.xr_ps.plot_phase_centers(label_all_fields, data_group)
|
|
104
|
-
|
|
105
|
-
def get_ps_len(self):
|
|
106
|
-
''' Returns number of ms_xdt in selected ps_xdt (if selected) '''
|
|
107
|
-
return len(self._get_ps_xdt())
|
|
108
|
-
|
|
109
|
-
def get_max_dims(self):
|
|
110
|
-
''' Returns maximum length of data dimensions in selected ps_xdt (if selected) '''
|
|
111
|
-
ps_xdt = self._get_ps_xdt()
|
|
112
|
-
return ps_xdt.xr_ps.get_max_dims()
|
|
113
|
-
|
|
114
|
-
def get_data_dimensions(self):
|
|
115
|
-
''' Return the maximum dimensions in selected ps_xdt (if selected) '''
|
|
116
|
-
dims = list(self.get_max_dims().keys())
|
|
117
|
-
if 'uvw_label' in dims:
|
|
118
|
-
dims.remove('uvw_label') # not a VISIBILITY/SPECTRUM data dim
|
|
119
|
-
return dims
|
|
120
|
-
|
|
121
|
-
def get_dimension_values(self, dimension):
|
|
122
|
-
''' Return sorted list of unique values for input dimension in ProcessingSet. '''
|
|
123
|
-
ps_xdt = self._get_ps_xdt()
|
|
124
|
-
dim_values = []
|
|
125
|
-
for ms_xdt in ps_xdt.values():
|
|
126
|
-
if dimension == 'baseline':
|
|
127
|
-
ant1_names = ms_xdt.baseline_antenna1_name.values
|
|
128
|
-
ant2_names = ms_xdt.baseline_antenna2_name.values
|
|
129
|
-
for baseline_id in ms_xdt.baseline_id:
|
|
130
|
-
dim_values.append(f"{ant1_names[baseline_id]} & {ant2_names[baseline_id]}")
|
|
131
|
-
else:
|
|
132
|
-
try:
|
|
133
|
-
dim_values.extend([value.item() for value in ms_xdt[dimension].values])
|
|
134
|
-
except TypeError:
|
|
135
|
-
dim_values.append(ms_xdt[dimension].values.item())
|
|
136
|
-
return sorted(set(dim_values))
|
|
137
|
-
|
|
138
|
-
def get_dimension_attrs(self, dim):
|
|
139
|
-
''' Return attributes dict for input dimension in ProcessingSet. '''
|
|
140
|
-
ps_xdt = self._get_ps_xdt()
|
|
141
|
-
return ps_xdt.get(0)[dim].attrs
|
|
142
|
-
|
|
143
|
-
def get_first_spw(self):
|
|
144
|
-
''' Return first spw name by id '''
|
|
145
|
-
spw_id_names = {}
|
|
146
|
-
ps_xdt = self._get_ps_xdt()
|
|
147
|
-
for ms_xdt in ps_xdt.values():
|
|
148
|
-
freq_xds = ms_xdt.frequency
|
|
149
|
-
spw_id_names[freq_xds.spectral_window_id] = freq_xds.spectral_window_name
|
|
150
|
-
|
|
151
|
-
first_spw_id = min(spw_id_names)
|
|
152
|
-
first_spw_name = spw_id_names[first_spw_id]
|
|
153
|
-
|
|
154
|
-
summary = self.get_summary()
|
|
155
|
-
spw_df = summary[summary['spw_name'] == first_spw_name]
|
|
156
|
-
start_freq = spw_df.at[spw_df.index[0], 'start_frequency']
|
|
157
|
-
end_freq = spw_df.at[spw_df.index[0], 'end_frequency']
|
|
158
|
-
self._logger.info(f"Selecting first spw {first_spw_name} (id {first_spw_id}) with frequency range {start_freq:e} - {end_freq:e}")
|
|
159
|
-
return first_spw_name
|
|
160
|
-
|
|
161
|
-
def select_data(self, selection):
|
|
162
|
-
''' Apply selection dict to ProcessingSet to create selected ps_xdt.
|
|
163
|
-
If previous selection done, apply to selected ps_xdt.
|
|
164
|
-
Add selection to previous selections. '''
|
|
165
|
-
ps_xdt = self._get_ps_xdt()
|
|
166
|
-
self._selected_ps_xdt = select_ps(ps_xdt, selection, self._logger)
|
|
167
|
-
if self._selection:
|
|
168
|
-
self._selection |= selection
|
|
169
|
-
else:
|
|
170
|
-
self._selection = selection
|
|
171
|
-
|
|
172
|
-
def clear_selection(self):
|
|
173
|
-
''' Clear previous selections and use original ps_xdt '''
|
|
174
|
-
self._selection = None
|
|
175
|
-
self._selected_ps_xdt = None
|
|
176
|
-
|
|
177
|
-
def get_vis_stats(self, selection, vis_axis):
|
|
178
|
-
''' Returns statistics (min, max, mean, std) for data selected by selection.
|
|
179
|
-
selection (dict): fields and values to select
|
|
180
|
-
'''
|
|
181
|
-
stats_ps_xdt = select_ps(self._ps_xdt, selection, self._logger)
|
|
182
|
-
data_group = selection['data_group'] if 'data_group' in selection else 'base'
|
|
183
|
-
return calculate_ps_stats(stats_ps_xdt, self._zarr_path, vis_axis, data_group, self._logger)
|
|
184
|
-
|
|
185
|
-
def get_correlated_data(self, data_group):
|
|
186
|
-
''' Returns name of 'correlated_data' in Processing Set data_group '''
|
|
187
|
-
ps_xdt = self._get_ps_xdt()
|
|
188
|
-
for ms_xdt in ps_xdt.values():
|
|
189
|
-
if data_group in ms_xdt.attrs['data_groups']:
|
|
190
|
-
return get_correlated_data(ms_xdt.ds, data_group)
|
|
191
|
-
raise RuntimeError(f"No correlated data for data group {data_group}")
|
|
192
|
-
|
|
193
|
-
def get_raster_data(self, plot_inputs):
|
|
194
|
-
''' Returns xarray Dataset after applying plot inputs and raster plane selection '''
|
|
195
|
-
return raster_data(self._get_ps_xdt(),
|
|
196
|
-
plot_inputs,
|
|
197
|
-
self._logger
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
def _get_ps_xdt(self):
|
|
201
|
-
''' Returns selected ps_xdt if selection has been done, else original ps_xdt '''
|
|
202
|
-
return self._selected_ps_xdt if self._selected_ps_xdt else self._ps_xdt
|
|
203
|
-
|
|
204
|
-
def _get_unique_values(self, df_col):
|
|
205
|
-
''' Return unique values in pandas Dataframe column, for summary '''
|
|
206
|
-
values = df_col.to_numpy()
|
|
207
|
-
try:
|
|
208
|
-
# numeric arrays
|
|
209
|
-
return np.unique(np.concatenate(values))
|
|
210
|
-
except ValueError:
|
|
211
|
-
# string arrays
|
|
212
|
-
all_values = [row[0] for row in values]
|
|
213
|
-
return np.unique(np.concatenate(all_values))
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Functions for reading MSv2 or zarr MSv4 into xradio ProcessingSet
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import os.path
|
|
6
|
-
|
|
7
|
-
from xradio.measurement_set.open_processing_set import open_processing_set
|
|
8
|
-
|
|
9
|
-
try:
|
|
10
|
-
# requires python-casacore
|
|
11
|
-
from xradio.measurement_set.convert_msv2_to_processing_set import convert_msv2_to_processing_set
|
|
12
|
-
__HAVE_CASACORE = True
|
|
13
|
-
except ImportError:
|
|
14
|
-
__HAVE_CASACORE = False
|
|
15
|
-
|
|
16
|
-
def get_processing_set(ms_path, logger):
|
|
17
|
-
'''
|
|
18
|
-
Read msv2 or zarr file into processing set
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
ms_path (str): path to MSv2 or MSv4 zarr file
|
|
22
|
-
Returns:
|
|
23
|
-
xradio ProcessingSet
|
|
24
|
-
'''
|
|
25
|
-
|
|
26
|
-
if not os.path.exists(ms_path):
|
|
27
|
-
raise RuntimeError(f"Visibility file {ms_path} does not exist")
|
|
28
|
-
|
|
29
|
-
# Remove trailing / or entire path is basename with no extension
|
|
30
|
-
if ms_path[-1] == '/':
|
|
31
|
-
ms_path = ms_path[:-1]
|
|
32
|
-
|
|
33
|
-
basename, ext = os.path.splitext(ms_path)
|
|
34
|
-
if ext == ".zarr":
|
|
35
|
-
zarr_path = ms_path
|
|
36
|
-
else:
|
|
37
|
-
if not __HAVE_CASACORE:
|
|
38
|
-
raise RuntimeError("Cannot convert MSv2 to xradio zarr file: python-casacore not installed.")
|
|
39
|
-
zarr_path = basename + ".ps.zarr"
|
|
40
|
-
if not os.path.exists(zarr_path):
|
|
41
|
-
logger.info(f"Converting input MS {ms_path} to zarr {zarr_path}")
|
|
42
|
-
convert_msv2_to_processing_set(
|
|
43
|
-
in_file=ms_path,
|
|
44
|
-
out_file=zarr_path
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
if not os.path.exists(zarr_path):
|
|
48
|
-
raise RuntimeError("Zarr file does not exist")
|
|
49
|
-
|
|
50
|
-
ps = open_processing_set(zarr_path)
|
|
51
|
-
if not ps or len(ps) == 0:
|
|
52
|
-
raise RuntimeError("Failed to read measurement set into processing set.")
|
|
53
|
-
logger.info(f"Processing set contains {len(ps)} msv4 datasets.")
|
|
54
|
-
|
|
55
|
-
return ps, zarr_path
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
Functions to create a raster xarray Dataset from xradio ProcessingSet after applying plot inputs
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
|
|
7
|
-
from xradio.measurement_set._utils._utils.stokes_types import stokes_types
|
|
8
|
-
|
|
9
|
-
from cubevis.data.measurement_set.processing_set._ps_concat import concat_ps_xdt
|
|
10
|
-
from cubevis.data.measurement_set.processing_set._ps_coords import set_datetime_coordinate
|
|
11
|
-
from cubevis.data.measurement_set.processing_set._ps_select import select_ps
|
|
12
|
-
from cubevis.data.measurement_set.processing_set._xds_data import get_axis_data
|
|
13
|
-
|
|
14
|
-
def raster_data(ps_xdt, plot_inputs, logger):
|
|
15
|
-
'''
|
|
16
|
-
Create raster xds: y_axis vs x_axis for vis axis.
|
|
17
|
-
ps_xdt (xarray DataTree): input datasets.
|
|
18
|
-
plot_inputs (dict): user inputs for plot
|
|
19
|
-
logger (graphviper logger): logger
|
|
20
|
-
Returns: selected xarray Dataset of visibility component and updated selection
|
|
21
|
-
'''
|
|
22
|
-
raster_xdt, dim_selection = _select_raster_ps_xdt(ps_xdt, plot_inputs, logger)
|
|
23
|
-
plot_inputs['dim_selection'] = dim_selection
|
|
24
|
-
|
|
25
|
-
# Create xds from concat ms_xds in ps
|
|
26
|
-
raster_xds = concat_ps_xdt(raster_xdt, logger)
|
|
27
|
-
correlated_data = plot_inputs['correlated_data']
|
|
28
|
-
if raster_xds[correlated_data].count() == 0:
|
|
29
|
-
raise RuntimeError("Plot failed: raster plane selection yielded data with all nan values.")
|
|
30
|
-
|
|
31
|
-
# Set complex component of vis data
|
|
32
|
-
raster_xds[correlated_data] = get_axis_data(raster_xds,
|
|
33
|
-
plot_inputs['vis_axis'],
|
|
34
|
-
plot_inputs['selection']['data_group_name']
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
# Convert float time to datetime
|
|
38
|
-
set_datetime_coordinate(raster_xds)
|
|
39
|
-
|
|
40
|
-
# Apply aggregator
|
|
41
|
-
raster_xds = aggregate_data(raster_xds, plot_inputs, logger)
|
|
42
|
-
|
|
43
|
-
logger.debug(f"Plotting visibility data with shape: {raster_xds[correlated_data].shape}")
|
|
44
|
-
return raster_xds
|
|
45
|
-
|
|
46
|
-
def _select_raster_ps_xdt(ps_xdt, plot_inputs, logger):
|
|
47
|
-
''' Select default dimensions if needed for raster data '''
|
|
48
|
-
# Determine which dims must be selected, add to selection, and do selection
|
|
49
|
-
input_selection = plot_inputs['selection']
|
|
50
|
-
dims_to_select = _get_raster_selection_dims(plot_inputs)
|
|
51
|
-
dim_selection = {} # return value
|
|
52
|
-
|
|
53
|
-
if dims_to_select:
|
|
54
|
-
for dim in dims_to_select:
|
|
55
|
-
# Select first value (by index) and add to dim selection, or apply iter_axis value
|
|
56
|
-
# (user selection would have been applied previously)
|
|
57
|
-
if dim not in input_selection:
|
|
58
|
-
dim_selection[dim] = _get_first_dim_value(ps_xdt, dim, plot_inputs, logger)
|
|
59
|
-
elif dim == plot_inputs['iter_axis']:
|
|
60
|
-
dim_selection[dim] = input_selection[dim]
|
|
61
|
-
if dim_selection:
|
|
62
|
-
logger.info(f"Applying raster plane selection (using first index or iter value): {dim_selection}")
|
|
63
|
-
return select_ps(ps_xdt, dim_selection, logger), dim_selection
|
|
64
|
-
return ps_xdt, dim_selection
|
|
65
|
-
|
|
66
|
-
def _get_raster_selection_dims(plot_inputs):
|
|
67
|
-
''' Return which dimensions should be selected for raster plot.
|
|
68
|
-
List of dimensions which are not x, y, or agg axis. '''
|
|
69
|
-
data_dims = plot_inputs['data_dims'].copy()
|
|
70
|
-
if plot_inputs['x_axis'] in data_dims:
|
|
71
|
-
data_dims.remove(plot_inputs['x_axis'])
|
|
72
|
-
if plot_inputs['y_axis'] in data_dims:
|
|
73
|
-
data_dims.remove(plot_inputs['y_axis'])
|
|
74
|
-
if plot_inputs['aggregator'] and plot_inputs['agg_axis']:
|
|
75
|
-
for axis in plot_inputs['agg_axis']:
|
|
76
|
-
data_dims.remove(axis)
|
|
77
|
-
return data_dims
|
|
78
|
-
|
|
79
|
-
def _get_first_dim_value(ps_xdt, dim, plot_inputs, logger):
|
|
80
|
-
''' Return value of first dimension by index for polarization or by value for others. '''
|
|
81
|
-
# If iter_axis, get first dim value after iter value is selected to avoid empty selected ps
|
|
82
|
-
iter_axis = plot_inputs['iter_axis'] if 'iter_axis' in plot_inputs else None
|
|
83
|
-
iter_ps = ps_xdt
|
|
84
|
-
if iter_axis:
|
|
85
|
-
iter_selection = {iter_axis: plot_inputs['selection'][iter_axis]}
|
|
86
|
-
iter_ps = select_ps(ps_xdt, iter_selection, logger)
|
|
87
|
-
|
|
88
|
-
values = []
|
|
89
|
-
if dim == "polarization":
|
|
90
|
-
# Get sorted list of polarization ids used
|
|
91
|
-
stokes = list(stokes_types.values())
|
|
92
|
-
for ms_xdt in iter_ps.values():
|
|
93
|
-
for val in ms_xdt.polarization.values:
|
|
94
|
-
values.append(stokes.index(val))
|
|
95
|
-
sorted_values = sorted(list(set(values)))
|
|
96
|
-
# Get pol name for pol id
|
|
97
|
-
return stokes[sorted_values[0]]
|
|
98
|
-
|
|
99
|
-
if dim == 'baseline':
|
|
100
|
-
for ms_xdt in iter_ps.values():
|
|
101
|
-
ant1_names = ms_xdt.baseline_antenna1_name.values
|
|
102
|
-
ant2_names = ms_xdt.baseline_antenna2_name.values
|
|
103
|
-
for baseline_id in ms_xdt.baseline_id.values:
|
|
104
|
-
values.append(ant1_names[baseline_id] + " & " + ant2_names[baseline_id])
|
|
105
|
-
return sorted(list(set(values)))[0]
|
|
106
|
-
|
|
107
|
-
# Get sorted values list
|
|
108
|
-
for ms_xdt in iter_ps.values():
|
|
109
|
-
values.extend(ms_xdt[dim].values.tolist())
|
|
110
|
-
return sorted(list(set(values)))[0]
|
|
111
|
-
|
|
112
|
-
def _add_index_dimensions(xds):
|
|
113
|
-
''' Add index coordinates for plotting if coord has dimension '''
|
|
114
|
-
# Baseline/antenna id
|
|
115
|
-
if "baseline" in xds.coords and xds.baseline.dims:
|
|
116
|
-
xds = xds.assign_coords({"baseline_id": (xds.baseline.dims, np.array(range(xds.baseline.size)))})
|
|
117
|
-
xds = xds.swap_dims({"baseline": "baseline_id"})
|
|
118
|
-
elif "antenna_name" in xds.coords and xds.antenna_name.dims:
|
|
119
|
-
xds = xds.assign_coords({"antenna_id": (xds.antenna_name.dims, np.array(range(xds.antenna_name.size)))})
|
|
120
|
-
|
|
121
|
-
# Polarization id
|
|
122
|
-
if "polarization" in xds.coords and xds.polarization.dims:
|
|
123
|
-
xds = xds.assign_coords({"polarization_id": (xds.polarization.dims, np.array(range(xds.polarization.size)))})
|
|
124
|
-
|
|
125
|
-
return xds
|
|
126
|
-
|
|
127
|
-
def aggregate_data(xds, plot_inputs, logger):
|
|
128
|
-
''' Apply aggregator to agg axis list. '''
|
|
129
|
-
if not plot_inputs['aggregator']:
|
|
130
|
-
return xds
|
|
131
|
-
|
|
132
|
-
aggregator = plot_inputs['aggregator']
|
|
133
|
-
agg_axis = plot_inputs['agg_axis']
|
|
134
|
-
agg_xds = xds
|
|
135
|
-
|
|
136
|
-
# Check if agg axes have been selected (selection or iteration) and are no longer a dimension
|
|
137
|
-
apply_agg_axis = [axis for axis in agg_axis if axis in xds.dims]
|
|
138
|
-
logger.debug(f"Applying {aggregator} to {apply_agg_axis}.")
|
|
139
|
-
|
|
140
|
-
if aggregator == 'max':
|
|
141
|
-
agg_xds = xds.max(dim=apply_agg_axis, keep_attrs=True)
|
|
142
|
-
elif aggregator == 'mean':
|
|
143
|
-
agg_xds = xds.mean(dim=apply_agg_axis, keep_attrs=True)
|
|
144
|
-
elif aggregator == 'median':
|
|
145
|
-
agg_xds = xds.median(dim=apply_agg_axis, keep_attrs=True)
|
|
146
|
-
elif aggregator == 'min':
|
|
147
|
-
agg_xds = xds.min(dim=apply_agg_axis, keep_attrs=True)
|
|
148
|
-
elif aggregator == 'std':
|
|
149
|
-
agg_xds = xds.std(dim=apply_agg_axis, keep_attrs=True)
|
|
150
|
-
elif aggregator == 'sum':
|
|
151
|
-
agg_xds = xds.sum(dim=apply_agg_axis, keep_attrs=True)
|
|
152
|
-
elif aggregator == 'var':
|
|
153
|
-
agg_xds = xds.var(dim=apply_agg_axis, keep_attrs=True)
|
|
154
|
-
return agg_xds
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
''' Apply selection dict to ProcessingSet and MeasurementSetXds '''
|
|
2
|
-
|
|
3
|
-
def select_ps(ps_xdt, selection, logger):
|
|
4
|
-
'''
|
|
5
|
-
Apply selection dict to Processing Set.
|
|
6
|
-
Select Processing Set first (ps summary columns), then each MeasurementSetXds (data_group etc.).
|
|
7
|
-
Returns dict of selected name, ms_xdt.
|
|
8
|
-
Throws exception for empty Processing Set (null selection).
|
|
9
|
-
'''
|
|
10
|
-
if not selection:
|
|
11
|
-
return ps_xdt
|
|
12
|
-
|
|
13
|
-
# Separate PS selection and MS selection
|
|
14
|
-
ps_summary = ps_xdt.xr_ps.summary()
|
|
15
|
-
ps_selection_keys = list(ps_summary.columns.array)
|
|
16
|
-
ps_selection_keys.append('data_group')
|
|
17
|
-
|
|
18
|
-
first_ms = ps_summary['name'][0]
|
|
19
|
-
ms_selection_keys = list(ps_xdt[first_ms].coords.keys())
|
|
20
|
-
|
|
21
|
-
# Sort selections into categories
|
|
22
|
-
ps_selection = {}
|
|
23
|
-
ms_selection = {}
|
|
24
|
-
antenna_selection = {}
|
|
25
|
-
for key, val in selection.items():
|
|
26
|
-
if key in ps_selection_keys and selection[key]:
|
|
27
|
-
ps_selection[key] = val
|
|
28
|
-
if key in ms_selection_keys and selection[key]:
|
|
29
|
-
ms_selection[key] = val
|
|
30
|
-
if 'antenna1' in key or 'antenna2' in key:
|
|
31
|
-
antenna_selection[key] = val
|
|
32
|
-
elif key == 'baseline':
|
|
33
|
-
ant1, ant2 = val.split('&')
|
|
34
|
-
antenna_selection['antenna1'] = ant1.strip()
|
|
35
|
-
antenna_selection['antenna2'] = ant2.strip()
|
|
36
|
-
|
|
37
|
-
# Do PSXdt selection
|
|
38
|
-
logger.debug(f"Applying selection to ProcessingSet: {ps_selection}")
|
|
39
|
-
|
|
40
|
-
if ps_selection:
|
|
41
|
-
selected_ps_xdt = ps_xdt.xr_ps.query(**ps_selection)
|
|
42
|
-
if len(selected_ps_xdt) == 0:
|
|
43
|
-
raise RuntimeError("Selection failed: ps selection yielded empty processing set.")
|
|
44
|
-
else:
|
|
45
|
-
selected_ps_xdt = ps_xdt.copy()
|
|
46
|
-
|
|
47
|
-
# Do MSXdt selection
|
|
48
|
-
return _select_ms_xdt(selected_ps_xdt, ms_selection, antenna_selection, logger)
|
|
49
|
-
|
|
50
|
-
def _select_ms_xdt(ps_xdt, ms_selection, antenna_selection, logger):
|
|
51
|
-
''' Apply selection to each MeasurementSetXds and return ProcessingSet.
|
|
52
|
-
Remove ms_xds which do not contain selection.
|
|
53
|
-
'''
|
|
54
|
-
# Done if no selection to apply
|
|
55
|
-
if not ms_selection and not antenna_selection:
|
|
56
|
-
return ps_xdt
|
|
57
|
-
|
|
58
|
-
logger.debug(f"Applying selection to measurement set: {ms_selection}, {antenna_selection}")
|
|
59
|
-
|
|
60
|
-
# Drop ms_xdt where selection fails
|
|
61
|
-
names_to_drop = []
|
|
62
|
-
|
|
63
|
-
for name, ms_xdt in ps_xdt.items():
|
|
64
|
-
try:
|
|
65
|
-
if antenna_selection:
|
|
66
|
-
for antenna, val in antenna_selection.items():
|
|
67
|
-
if antenna == 'antenna1':
|
|
68
|
-
ms_xdt = ms_xdt.sel(baseline_id=ms_xdt.baseline_antenna1_name==val)
|
|
69
|
-
else:
|
|
70
|
-
ms_xdt = ms_xdt.sel(baseline_id=ms_xdt.baseline_antenna2_name==val)
|
|
71
|
-
|
|
72
|
-
if ms_xdt.baseline_id.size == 1:
|
|
73
|
-
# Select baseline_id to remove dimension
|
|
74
|
-
ms_xdt = ms_xdt.sel(baseline_id=ms_xdt.baseline_id.item())
|
|
75
|
-
elif ms_xdt.baseline_id.size == 0:
|
|
76
|
-
names_to_drop.append(name)
|
|
77
|
-
continue
|
|
78
|
-
|
|
79
|
-
ms_xdt = ms_xdt.xr_ms.sel(**ms_selection)
|
|
80
|
-
ps_xdt[name] = ms_xdt
|
|
81
|
-
except KeyError:
|
|
82
|
-
# selection not in this ms_xdt, do not include in returned ps_xdt
|
|
83
|
-
names_to_drop.append(name)
|
|
84
|
-
|
|
85
|
-
if names_to_drop:
|
|
86
|
-
ps_xdt = ps_xdt.drop_nodes(names_to_drop)
|
|
87
|
-
|
|
88
|
-
if len(ps_xdt) == 0:
|
|
89
|
-
raise RuntimeError("Selection failed: ms selection yielded empty processing set.")
|
|
90
|
-
|
|
91
|
-
return ps_xdt
|