xradio 0.0.55__py3-none-any.whl → 0.0.58__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.
- xradio/__init__.py +2 -2
- xradio/_utils/_casacore/casacore_from_casatools.py +1001 -0
- xradio/_utils/_casacore/tables.py +6 -1
- xradio/_utils/coord_math.py +22 -23
- xradio/_utils/dict_helpers.py +76 -11
- xradio/_utils/schema.py +5 -2
- xradio/_utils/zarr/common.py +1 -73
- xradio/image/_util/_casacore/common.py +11 -3
- xradio/image/_util/_casacore/xds_from_casacore.py +59 -35
- xradio/image/_util/_casacore/xds_to_casacore.py +47 -16
- xradio/image/_util/_fits/xds_from_fits.py +172 -77
- xradio/image/_util/casacore.py +9 -4
- xradio/image/_util/common.py +4 -4
- xradio/image/_util/image_factory.py +8 -8
- xradio/image/image.py +45 -5
- xradio/measurement_set/__init__.py +19 -9
- xradio/measurement_set/_utils/__init__.py +1 -3
- xradio/measurement_set/_utils/_msv2/__init__.py +0 -0
- xradio/measurement_set/_utils/_msv2/_tables/read.py +35 -90
- xradio/measurement_set/_utils/_msv2/_tables/read_main_table.py +6 -686
- xradio/measurement_set/_utils/_msv2/_tables/table_query.py +13 -3
- xradio/measurement_set/_utils/_msv2/conversion.py +129 -145
- xradio/measurement_set/_utils/_msv2/create_antenna_xds.py +9 -16
- xradio/measurement_set/_utils/_msv2/create_field_and_source_xds.py +125 -221
- xradio/measurement_set/_utils/_msv2/msv2_to_msv4_meta.py +1 -2
- xradio/measurement_set/_utils/_msv2/msv4_info_dicts.py +13 -8
- xradio/measurement_set/_utils/_msv2/msv4_sub_xdss.py +27 -72
- xradio/measurement_set/_utils/_msv2/partition_queries.py +5 -262
- xradio/measurement_set/_utils/_msv2/subtables.py +0 -107
- xradio/measurement_set/_utils/_utils/interpolate.py +60 -0
- xradio/measurement_set/_utils/_zarr/encoding.py +2 -7
- xradio/measurement_set/convert_msv2_to_processing_set.py +0 -2
- xradio/measurement_set/load_processing_set.py +2 -2
- xradio/measurement_set/measurement_set_xdt.py +14 -14
- xradio/measurement_set/open_processing_set.py +1 -3
- xradio/measurement_set/processing_set_xdt.py +41 -835
- xradio/measurement_set/schema.py +96 -123
- xradio/schema/check.py +91 -97
- xradio/schema/dataclass.py +159 -22
- xradio/schema/export.py +99 -0
- xradio/schema/metamodel.py +51 -16
- xradio/schema/typing.py +5 -5
- {xradio-0.0.55.dist-info → xradio-0.0.58.dist-info}/METADATA +43 -11
- xradio-0.0.58.dist-info/RECORD +65 -0
- {xradio-0.0.55.dist-info → xradio-0.0.58.dist-info}/WHEEL +1 -1
- xradio/image/_util/fits.py +0 -13
- xradio/measurement_set/_utils/_msv2/_tables/load.py +0 -63
- xradio/measurement_set/_utils/_msv2/_tables/load_main_table.py +0 -487
- xradio/measurement_set/_utils/_msv2/_tables/read_subtables.py +0 -395
- xradio/measurement_set/_utils/_msv2/_tables/write.py +0 -320
- xradio/measurement_set/_utils/_msv2/_tables/write_exp_api.py +0 -385
- xradio/measurement_set/_utils/_msv2/chunks.py +0 -115
- xradio/measurement_set/_utils/_msv2/descr.py +0 -165
- xradio/measurement_set/_utils/_msv2/msv2_msv3.py +0 -7
- xradio/measurement_set/_utils/_msv2/partitions.py +0 -392
- xradio/measurement_set/_utils/_utils/cds.py +0 -40
- xradio/measurement_set/_utils/_utils/xds_helper.py +0 -404
- xradio/measurement_set/_utils/_zarr/read.py +0 -263
- xradio/measurement_set/_utils/_zarr/write.py +0 -329
- xradio/measurement_set/_utils/msv2.py +0 -106
- xradio/measurement_set/_utils/zarr.py +0 -133
- xradio-0.0.55.dist-info/RECORD +0 -77
- {xradio-0.0.55.dist-info → xradio-0.0.58.dist-info}/licenses/LICENSE.txt +0 -0
- {xradio-0.0.55.dist-info → xradio-0.0.58.dist-info}/top_level.txt +0 -0
|
@@ -18,10 +18,9 @@ from xradio.measurement_set._utils._msv2._tables.read import (
|
|
|
18
18
|
load_generic_table,
|
|
19
19
|
)
|
|
20
20
|
from xradio._utils.list_and_array import cast_to_str, get_pad_value
|
|
21
|
-
|
|
21
|
+
from xradio._utils.dict_helpers import make_quantity_attrs
|
|
22
22
|
from xradio._utils.coord_math import (
|
|
23
23
|
convert_to_si_units,
|
|
24
|
-
add_position_offsets,
|
|
25
24
|
wrap_to_pi,
|
|
26
25
|
)
|
|
27
26
|
|
|
@@ -45,7 +44,7 @@ def create_field_and_source_xds(
|
|
|
45
44
|
is_single_dish: bool,
|
|
46
45
|
time_min_max: Tuple[np.float64, np.float64],
|
|
47
46
|
ephemeris_interpolate: bool = True,
|
|
48
|
-
) -> tuple[xr.Dataset, int]:
|
|
47
|
+
) -> tuple[xr.Dataset, np.ndarray, int]:
|
|
49
48
|
"""
|
|
50
49
|
Create a field and source xarray dataset (xds) from the given input file, field ID, and spectral window ID.
|
|
51
50
|
Data is extracted from the FIELD and SOURCE tables and if there is ephemeris data, it is also extracted.
|
|
@@ -72,6 +71,8 @@ def create_field_and_source_xds(
|
|
|
72
71
|
-------
|
|
73
72
|
field_and_source_xds : xr.Dataset
|
|
74
73
|
The xarray dataset containing the field and source information.
|
|
74
|
+
source_id : np.ndarray[int]
|
|
75
|
+
Source ID(s) corresponding to the field(s)
|
|
75
76
|
num_lines : int
|
|
76
77
|
Sum of num_lines for all unique sources.
|
|
77
78
|
"""
|
|
@@ -158,6 +159,10 @@ def extract_ephemeris_info(
|
|
|
158
159
|
# Consequently a lot of hardcoding is needed to extract the information.
|
|
159
160
|
# https://casadocs.readthedocs.io/en/latest/notebooks/external-data.html
|
|
160
161
|
|
|
162
|
+
xds = xds.assign_coords(
|
|
163
|
+
{"sky_dis_label": ["dist"], "cartesian_pos_label": ["x", "y", "z"]}
|
|
164
|
+
)
|
|
165
|
+
|
|
161
166
|
# Only read data between the min and max times of the visibility data in the MSv4.
|
|
162
167
|
min_max_mjd = (
|
|
163
168
|
convert_casacore_time_to_mjd(time_min_max[0]),
|
|
@@ -214,44 +219,64 @@ def extract_ephemeris_info(
|
|
|
214
219
|
temp_xds = xr.Dataset()
|
|
215
220
|
|
|
216
221
|
# Add mandatory data: OBSERVER_POSITION
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
+
# Convert Observer position to geodetic coordinates
|
|
223
|
+
from astropy import units as u
|
|
224
|
+
from astropy.coordinates import EarthLocation
|
|
225
|
+
from astropy.time import Time
|
|
226
|
+
|
|
227
|
+
# Create an EarthLocation object for the geodetic coordinates
|
|
228
|
+
# Assume that geodetic coordinates are given in degrees and meters
|
|
229
|
+
location = EarthLocation.from_geodetic(
|
|
230
|
+
lon=ephemeris_meta["GeoLong"] * u.deg,
|
|
231
|
+
lat=ephemeris_meta["GeoLat"] * u.deg,
|
|
232
|
+
height=ephemeris_meta["GeoDist"] * u.m,
|
|
233
|
+
ellipsoid="WGS84", # Explicitly specify WGS84
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# Get the ITRS Cartesian coordinates (x, y, z)
|
|
237
|
+
observer_position = location.itrs.cartesian.xyz
|
|
238
|
+
|
|
222
239
|
temp_xds["OBSERVER_POSITION"] = xr.DataArray(
|
|
223
|
-
observer_position, dims=["
|
|
240
|
+
observer_position, dims=["cartesian_pos_label"]
|
|
224
241
|
)
|
|
225
242
|
temp_xds["OBSERVER_POSITION"].attrs.update(
|
|
226
243
|
{
|
|
227
244
|
"type": "location",
|
|
228
|
-
"units":
|
|
229
|
-
"data": observer_position,
|
|
245
|
+
"units": "m",
|
|
230
246
|
"frame": "ITRS",
|
|
231
247
|
"origin_object_name": "Earth",
|
|
232
248
|
"coordinate_system": ephemeris_meta["obsloc"].lower(),
|
|
233
|
-
"ellipsoid": "WGS84",
|
|
234
249
|
}
|
|
235
|
-
)
|
|
250
|
+
)
|
|
236
251
|
|
|
237
|
-
|
|
238
|
-
temp_xds["SOURCE_LOCATION"] = xr.DataArray(
|
|
252
|
+
temp_xds["SOURCE_DIRECTION"] = xr.DataArray(
|
|
239
253
|
np.column_stack(
|
|
240
254
|
(
|
|
241
255
|
ephemeris_xds["RA"].data,
|
|
242
256
|
ephemeris_xds["DEC"].data,
|
|
243
|
-
ephemeris_xds["Rho"].data,
|
|
244
257
|
)
|
|
245
258
|
),
|
|
246
|
-
dims=["time_ephemeris", "
|
|
259
|
+
dims=["time_ephemeris", "sky_dir_label"],
|
|
247
260
|
)
|
|
261
|
+
|
|
262
|
+
temp_xds["SOURCE_DISTANCE"] = xr.DataArray(
|
|
263
|
+
np.column_stack((ephemeris_xds["Rho"].data,)),
|
|
264
|
+
dims=["time_ephemeris", "sky_dis_label"],
|
|
265
|
+
)
|
|
266
|
+
|
|
248
267
|
# Have to use cast_to_str because the ephemeris table units are not consistently in a list or a string.
|
|
249
|
-
sky_coord_units =
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
]
|
|
254
|
-
|
|
268
|
+
sky_coord_units = cast_to_str(
|
|
269
|
+
ephemeris_column_description["RA"]["keywords"][unit_keyword]
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
temp_xds["SOURCE_DIRECTION"].attrs.update(
|
|
273
|
+
{"type": "sky_coord", "frame": sky_coord_frame, "units": sky_coord_units}
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
sky_coord_units = cast_to_str(
|
|
277
|
+
ephemeris_column_description["Rho"]["keywords"][unit_keyword]
|
|
278
|
+
)
|
|
279
|
+
temp_xds["SOURCE_DISTANCE"].attrs.update(
|
|
255
280
|
{"type": "sky_coord", "frame": sky_coord_frame, "units": sky_coord_units}
|
|
256
281
|
)
|
|
257
282
|
|
|
@@ -281,16 +306,13 @@ def extract_ephemeris_info(
|
|
|
281
306
|
msv4_var_name = msv4_variable_def[0]
|
|
282
307
|
if msv4_var_name in temp_xds:
|
|
283
308
|
temp_xds[msv4_var_name].attrs.update(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
)
|
|
292
|
-
],
|
|
293
|
-
}
|
|
309
|
+
make_quantity_attrs(
|
|
310
|
+
cast_to_str(
|
|
311
|
+
ephemeris_column_description[generic_var_name]["keywords"][
|
|
312
|
+
unit_keyword
|
|
313
|
+
]
|
|
314
|
+
)
|
|
315
|
+
)
|
|
294
316
|
)
|
|
295
317
|
|
|
296
318
|
# Add optional data: SUB_OBSERVER_DIRECTION and SUB_SOLAR_POSITION
|
|
@@ -307,10 +329,9 @@ def extract_ephemeris_info(
|
|
|
307
329
|
(
|
|
308
330
|
ephemeris_xds[key_lon].data,
|
|
309
331
|
ephemeris_xds[key_lat].data,
|
|
310
|
-
np.zeros(ephemeris_xds[key_lon].shape),
|
|
311
332
|
)
|
|
312
333
|
),
|
|
313
|
-
dims=["time_ephemeris", "
|
|
334
|
+
dims=["time_ephemeris", "ellipsoid_dir_label"],
|
|
314
335
|
)
|
|
315
336
|
|
|
316
337
|
temp_xds["SUB_OBSERVER_DIRECTION"].attrs.update(
|
|
@@ -319,54 +340,55 @@ def extract_ephemeris_info(
|
|
|
319
340
|
"frame": "Undefined",
|
|
320
341
|
"origin_object_name": ephemeris_meta["NAME"],
|
|
321
342
|
"coordinate_system": "planetodetic",
|
|
322
|
-
"units":
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
),
|
|
326
|
-
cast_to_str(
|
|
327
|
-
ephemeris_column_description[key_lat]["keywords"][unit_keyword]
|
|
328
|
-
),
|
|
329
|
-
"m",
|
|
330
|
-
],
|
|
343
|
+
"units": cast_to_str(
|
|
344
|
+
ephemeris_column_description[key_lon]["keywords"][unit_keyword]
|
|
345
|
+
),
|
|
331
346
|
}
|
|
332
347
|
)
|
|
333
348
|
|
|
334
349
|
if "SI_lon" in ephemeris_xds.data_vars:
|
|
335
|
-
temp_xds["
|
|
350
|
+
temp_xds["SUB_SOLAR_DIRECTION"] = xr.DataArray(
|
|
336
351
|
np.column_stack(
|
|
337
352
|
(
|
|
338
353
|
ephemeris_xds["SI_lon"].data,
|
|
339
354
|
ephemeris_xds["SI_lat"].data,
|
|
340
|
-
ephemeris_xds["r"].data,
|
|
341
355
|
)
|
|
342
356
|
),
|
|
343
|
-
dims=["time_ephemeris", "
|
|
357
|
+
dims=["time_ephemeris", "ellipsoid_dir_label"],
|
|
344
358
|
)
|
|
345
|
-
temp_xds["
|
|
359
|
+
temp_xds["SUB_SOLAR_DIRECTION"].attrs.update(
|
|
346
360
|
{
|
|
347
361
|
"type": "location",
|
|
348
362
|
"frame": "Undefined",
|
|
349
363
|
"origin_object_name": "Sun",
|
|
350
364
|
"coordinate_system": "planetodetic",
|
|
351
|
-
"units":
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
365
|
+
"units": cast_to_str(
|
|
366
|
+
ephemeris_column_description["SI_lon"]["keywords"][unit_keyword]
|
|
367
|
+
),
|
|
368
|
+
}
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
temp_xds["SUB_SOLAR_DISTANCE"] = xr.DataArray(
|
|
372
|
+
[ephemeris_xds["r"].data],
|
|
373
|
+
dims=["time_ephemeris", "ellipsoid_dis_label"],
|
|
374
|
+
)
|
|
375
|
+
temp_xds["SUB_SOLAR_DISTANCE"].attrs.update(
|
|
376
|
+
{
|
|
377
|
+
"type": "location",
|
|
378
|
+
"frame": "Undefined",
|
|
379
|
+
"origin_object_name": "Sun",
|
|
380
|
+
"coordinate_system": "planetodetic",
|
|
381
|
+
"units": cast_to_str(
|
|
382
|
+
ephemeris_column_description["r"]["keywords"][unit_keyword]
|
|
383
|
+
),
|
|
362
384
|
}
|
|
363
385
|
)
|
|
364
386
|
|
|
365
387
|
# We are using the "time_ephemeris" label because it might not match the optional time axis of the source and field info. If ephemeris_interpolate=True then rename it to time.
|
|
366
388
|
coords = {
|
|
367
|
-
"
|
|
389
|
+
"ellipsoid_dir_label": ["lon", "lat"],
|
|
390
|
+
"ellipsoid_dis_label": ["dist"],
|
|
368
391
|
"time_ephemeris": ephemeris_xds["time"].data,
|
|
369
|
-
"sky_pos_label": ["ra", "dec", "dist"],
|
|
370
392
|
}
|
|
371
393
|
temp_xds = temp_xds.assign_coords(coords)
|
|
372
394
|
temp_xds["time_ephemeris"].attrs.update(standard_time_coord_attrs)
|
|
@@ -379,10 +401,18 @@ def extract_ephemeris_info(
|
|
|
379
401
|
temp_xds = rename_and_interpolate_to_time(
|
|
380
402
|
temp_xds, "time_ephemeris", interp_time, "field_and_source_xds"
|
|
381
403
|
)
|
|
382
|
-
|
|
404
|
+
source_direction_interp = temp_xds["SOURCE_DIRECTION"]
|
|
405
|
+
source_distance_interp = temp_xds["SOURCE_DISTANCE"]
|
|
406
|
+
|
|
383
407
|
else:
|
|
384
|
-
|
|
385
|
-
temp_xds["
|
|
408
|
+
source_direction_interp = interpolate_to_time(
|
|
409
|
+
temp_xds["SOURCE_DIRECTION"],
|
|
410
|
+
interp_time,
|
|
411
|
+
"field_and_source_xds",
|
|
412
|
+
"time_ephemeris",
|
|
413
|
+
)
|
|
414
|
+
source_distance_interp = interpolate_to_time(
|
|
415
|
+
temp_xds["SOURCE_DISTANCE"],
|
|
386
416
|
interp_time,
|
|
387
417
|
"field_and_source_xds",
|
|
388
418
|
"time_ephemeris",
|
|
@@ -390,68 +420,38 @@ def extract_ephemeris_info(
|
|
|
390
420
|
|
|
391
421
|
xds = xr.merge([xds, temp_xds])
|
|
392
422
|
|
|
393
|
-
# Add the
|
|
394
|
-
# We also need to add a distance dimension to the FIELD_PHASE_CENTER or FIELD_REFERENCE_CENTER to match the
|
|
395
|
-
#
|
|
423
|
+
# Add the SOURCE_DIRECTION to the FIELD_PHASE_CENTER or FIELD_REFERENCE_CENTER. Ephemeris obs: When loaded from the MSv2 field table the FIELD_REFERENCE_CENTER or FIELD_PHASE_CENTER only contain an offset from the SOURCE_DIRECTION.
|
|
424
|
+
# We also need to add a distance dimension to the FIELD_PHASE_CENTER or FIELD_REFERENCE_CENTER to match the SOURCE_DIRECTION.
|
|
425
|
+
# FIELD_PHASE_CENTER_DIRECTION is used for interferometer data and FIELD_REFERENCE_CENTER_DIRECTION is used for single dish data.
|
|
396
426
|
if is_single_dish:
|
|
397
|
-
|
|
427
|
+
center_dir_dv = "FIELD_REFERENCE_CENTER_DIRECTION"
|
|
428
|
+
center_dis_dv = "FIELD_REFERENCE_CENTER_DISTANCE"
|
|
398
429
|
else:
|
|
399
|
-
|
|
430
|
+
center_dir_dv = "FIELD_PHASE_CENTER_DIRECTION"
|
|
431
|
+
center_dis_dv = "FIELD_PHASE_CENTER_DISTANCE"
|
|
400
432
|
|
|
401
433
|
xds = xds.sel(field_name=field_names) # Expand for all times in ms
|
|
402
434
|
xds = xds.assign_coords({"time": ("field_name", interp_time)})
|
|
403
435
|
xds["time"].attrs.update(standard_time_coord_attrs)
|
|
404
436
|
xds = xds.swap_dims({"field_name": "time"})
|
|
405
437
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
xds[center_dv].values + source_location_interp[:, 0:2].values
|
|
438
|
+
field_phase_center_direction = wrap_to_pi(
|
|
439
|
+
xds[center_dir_dv].values + source_direction_interp.values
|
|
409
440
|
)
|
|
410
441
|
|
|
411
|
-
|
|
412
|
-
|
|
442
|
+
xds[center_dir_dv] = xr.DataArray(
|
|
443
|
+
field_phase_center_direction,
|
|
444
|
+
dims=["time", "sky_dir_label"],
|
|
413
445
|
)
|
|
414
446
|
|
|
415
|
-
|
|
416
|
-
|
|
447
|
+
xds[center_dis_dv] = xr.DataArray(
|
|
448
|
+
source_distance_interp.values,
|
|
449
|
+
dims=["time", "sky_dis_label"],
|
|
417
450
|
)
|
|
418
451
|
|
|
419
|
-
xds[
|
|
420
|
-
field_phase_center,
|
|
421
|
-
dims=["time", "sky_pos_label"],
|
|
422
|
-
)
|
|
423
|
-
|
|
424
|
-
# if "time" in xds[center_dv].coords:
|
|
425
|
-
# assert (
|
|
426
|
-
# interp_time is not None
|
|
427
|
-
# ), 'ephemeris_interpolate must be True if there is ephemeris data and multiple fields (this will occur if "FIELD_ID" is not in partition_scheme).'
|
|
428
|
-
|
|
429
|
-
# field_phase_center = wrap_to_pi(
|
|
430
|
-
# xds[center_dv].values + xds["SOURCE_LOCATION"][:, 0:2].values
|
|
431
|
-
# )
|
|
432
|
-
# field_phase_center = np.column_stack(
|
|
433
|
-
# (field_phase_center, np.zeros(xds[center_dv].values.shape[0]))
|
|
434
|
-
# )
|
|
435
|
-
# field_phase_center[:, -1] = (
|
|
436
|
-
# field_phase_center[:, -1] + xds["SOURCE_LOCATION"][:, -1].values
|
|
437
|
-
# )
|
|
438
|
-
|
|
439
|
-
# xds[center_dv] = xr.DataArray(
|
|
440
|
-
# field_phase_center,
|
|
441
|
-
# dims=[xds["SOURCE_LOCATION"].dims[0], "sky_pos_label"],
|
|
442
|
-
# )
|
|
443
|
-
# else:
|
|
444
|
-
# field_phase_center = (
|
|
445
|
-
# np.append(xds[center_dv].values, 0) + xds["SOURCE_LOCATION"].values
|
|
446
|
-
# )
|
|
447
|
-
# field_phase_center[:, 0:2] = wrap_to_pi(field_phase_center[:, 0:2])
|
|
448
|
-
|
|
449
|
-
# xds[center_dv] = xr.DataArray(
|
|
450
|
-
# field_phase_center,
|
|
451
|
-
# dims=[xds["SOURCE_LOCATION"].dims[0], "sky_pos_label"],
|
|
452
|
-
# )
|
|
452
|
+
xds[center_dir_dv].attrs.update(xds["SOURCE_DIRECTION"].attrs)
|
|
453
453
|
|
|
454
|
-
xds[
|
|
454
|
+
xds[center_dis_dv].attrs.update(xds["SOURCE_DISTANCE"].attrs)
|
|
455
455
|
|
|
456
456
|
return xds
|
|
457
457
|
|
|
@@ -611,7 +611,7 @@ def extract_source_info(
|
|
|
611
611
|
|
|
612
612
|
if all(source_id == -1):
|
|
613
613
|
logger.warning(
|
|
614
|
-
|
|
614
|
+
"Source_id is -1. No source information will be included in the field_and_source_xds."
|
|
615
615
|
)
|
|
616
616
|
xds = xds.assign_coords(
|
|
617
617
|
{"source_name": ("field_name", unknown)}
|
|
@@ -655,7 +655,7 @@ def extract_source_info(
|
|
|
655
655
|
# ), "Can only process source table with a single time entry for a source_id and spectral_window_id."
|
|
656
656
|
if len(source_xds.TIME) > len(unique_source_id):
|
|
657
657
|
logger.warning(
|
|
658
|
-
|
|
658
|
+
"Source table has more than one time entry for a source_id and spectral_window_id. This is not currently supported. Only the first time entry will be used."
|
|
659
659
|
)
|
|
660
660
|
source_xds = source_xds.drop_duplicates("SOURCE_ID", keep="first")
|
|
661
661
|
|
|
@@ -689,9 +689,6 @@ def extract_source_info(
|
|
|
689
689
|
# If ephemeris data is present we ignore the SOURCE_DIRECTION in the source table.
|
|
690
690
|
if not is_ephemeris:
|
|
691
691
|
direction_msv2_col = "DIRECTION"
|
|
692
|
-
msv4_measure = column_description_casacore_to_msv4_measure(
|
|
693
|
-
source_column_description[direction_msv2_col]
|
|
694
|
-
)
|
|
695
692
|
|
|
696
693
|
msv2_direction_dims = source_xds[direction_msv2_col].dims
|
|
697
694
|
if (
|
|
@@ -709,7 +706,7 @@ def extract_source_info(
|
|
|
709
706
|
location_msv4_measure = column_description_casacore_to_msv4_measure(
|
|
710
707
|
source_column_description[direction_msv2_col]
|
|
711
708
|
)
|
|
712
|
-
xds["
|
|
709
|
+
xds["SOURCE_DIRECTION"] = xr.DataArray(
|
|
713
710
|
direction_var.data, dims=direction_dims, attrs=location_msv4_measure
|
|
714
711
|
)
|
|
715
712
|
|
|
@@ -739,14 +736,15 @@ def extract_source_info(
|
|
|
739
736
|
|
|
740
737
|
# Need to add doppler info if present. Add check.
|
|
741
738
|
try:
|
|
742
|
-
|
|
739
|
+
load_generic_table(
|
|
743
740
|
path,
|
|
744
741
|
"DOPPLER",
|
|
745
742
|
)
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
743
|
+
logger.warning(
|
|
744
|
+
"Doppler table present. Please open an issue on "
|
|
745
|
+
"https://github.com/casangi/xradio/issues so that we can add support for this."
|
|
746
|
+
)
|
|
747
|
+
except ValueError:
|
|
750
748
|
pass
|
|
751
749
|
|
|
752
750
|
xds = xds.assign_coords(coords)
|
|
@@ -756,50 +754,6 @@ def extract_source_info(
|
|
|
756
754
|
return xds, np.sum(num_lines[unique_source_ids_indices])
|
|
757
755
|
|
|
758
756
|
|
|
759
|
-
def make_field_dims_and_coords(
|
|
760
|
-
field_xds: xr.Dataset, field_id: Union[int, np.ndarray], field_times: list
|
|
761
|
-
) -> tuple[list, dict]:
|
|
762
|
-
"""
|
|
763
|
-
Produces the dimensions and coordinates used in the field data variables
|
|
764
|
-
extracted from the MSv2 FIELD subtable (FIELD_PHASE_CENTER/
|
|
765
|
-
FIELD_REFERENCE_CENTER).
|
|
766
|
-
|
|
767
|
-
Parameters:
|
|
768
|
-
----------
|
|
769
|
-
field_xds: xr.Dataset
|
|
770
|
-
generic field xarray dataset
|
|
771
|
-
field_id: Union[int, np.ndarray]
|
|
772
|
-
field_id of the dataset
|
|
773
|
-
field_times:
|
|
774
|
-
Unique times for the dataset (when not partitioning by FIELD_ID)
|
|
775
|
-
|
|
776
|
-
Returns:
|
|
777
|
-
-------
|
|
778
|
-
tuple : tuple[list, dict]
|
|
779
|
-
The dimensions and coordinates to use with field data variables. The
|
|
780
|
-
dimensions are produced as a list of dimension names, and the
|
|
781
|
-
coordinates as a dict for xarray coords.
|
|
782
|
-
"""
|
|
783
|
-
|
|
784
|
-
coords = {"sky_dir_label": ["ra", "dec"]}
|
|
785
|
-
|
|
786
|
-
# field_times is the same as the time axis in the main MSv4 dataset and is used if more than one field is present.
|
|
787
|
-
if field_times is not None:
|
|
788
|
-
coords["time"] = field_times
|
|
789
|
-
dims = ["time", "sky_dir_label"]
|
|
790
|
-
coords["field_name"] = (
|
|
791
|
-
"time",
|
|
792
|
-
np.char.add(field_xds["NAME"].data, np.char.add("_", field_id.astype(str))),
|
|
793
|
-
)
|
|
794
|
-
# coords["field_id"] = ("time", field_id)
|
|
795
|
-
else:
|
|
796
|
-
coords["field_name"] = field_xds["NAME"].values.item() + "_" + str(field_id)
|
|
797
|
-
# coords["field_id"] = field_id
|
|
798
|
-
dims = ["field_name", "sky_dir_label"]
|
|
799
|
-
|
|
800
|
-
return dims, coords
|
|
801
|
-
|
|
802
|
-
|
|
803
757
|
def extract_field_info_and_check_ephemeris(
|
|
804
758
|
field_and_source_xds: xr.Dataset,
|
|
805
759
|
in_file: str,
|
|
@@ -892,14 +846,17 @@ def extract_field_info_and_check_ephemeris(
|
|
|
892
846
|
if is_single_dish:
|
|
893
847
|
to_new_data_variables = {
|
|
894
848
|
"REFERENCE_DIR": [
|
|
895
|
-
"
|
|
849
|
+
"FIELD_REFERENCE_CENTER_DIRECTION",
|
|
896
850
|
["field_name", "sky_dir_label"],
|
|
897
851
|
],
|
|
898
852
|
"FIELD_ID": ["FIELD_ID", ["field_name"]],
|
|
899
853
|
}
|
|
900
854
|
else:
|
|
901
855
|
to_new_data_variables = {
|
|
902
|
-
"PHASE_DIR": [
|
|
856
|
+
"PHASE_DIR": [
|
|
857
|
+
"FIELD_PHASE_CENTER_DIRECTION",
|
|
858
|
+
["field_name", "sky_dir_label"],
|
|
859
|
+
],
|
|
903
860
|
# "DELAY_DIR": ["FIELD_DELAY_CENTER",["field_name", "sky_dir_label"]],
|
|
904
861
|
# "REFERENCE_DIR": ["FIELD_REFERENCE_CENTER",["field_name", "sky_dir_label"]],
|
|
905
862
|
}
|
|
@@ -937,59 +894,6 @@ def extract_field_info_and_check_ephemeris(
|
|
|
937
894
|
# field_id shouldn ot be in final xds, and no longer needed past this point
|
|
938
895
|
field_and_source_xds = field_and_source_xds.drop_vars("field_id")
|
|
939
896
|
|
|
940
|
-
# dims, coords = make_field_dims_and_coords(field_xds, field_id, field_times)
|
|
941
|
-
|
|
942
|
-
# if is_single_dish:
|
|
943
|
-
# field_data_variables = {
|
|
944
|
-
# "REFERENCE_DIR": "FIELD_REFERENCE_CENTER",
|
|
945
|
-
# }
|
|
946
|
-
# else:
|
|
947
|
-
# field_data_variables = {
|
|
948
|
-
# # "DELAY_DIR": "FIELD_DELAY_CENTER",
|
|
949
|
-
# "PHASE_DIR": "FIELD_PHASE_CENTER",
|
|
950
|
-
# # "REFERENCE_DIR": "FIELD_REFERENCE_CENTER",
|
|
951
|
-
# }
|
|
952
|
-
|
|
953
|
-
# field_column_description = field_xds.attrs["other"]["msv2"]["ctds_attrs"][
|
|
954
|
-
# "column_descriptions"
|
|
955
|
-
# ]
|
|
956
|
-
|
|
957
|
-
# delay_dir_ref_col = "DelayDir_Ref"
|
|
958
|
-
# if field_xds.get(delay_dir_ref_col) is None:
|
|
959
|
-
# delaydir_ref = None
|
|
960
|
-
# else:
|
|
961
|
-
# delaydir_ref = check_if_consistent(
|
|
962
|
-
# field_xds.get(delay_dir_ref_col), delay_dir_ref_col
|
|
963
|
-
# )
|
|
964
|
-
|
|
965
|
-
# for generic_name, msv4_name in field_data_variables.items():
|
|
966
|
-
# msv4_measure = column_description_casacore_to_msv4_measure(
|
|
967
|
-
# field_column_description[generic_name], ref_code=delaydir_ref
|
|
968
|
-
# )
|
|
969
|
-
|
|
970
|
-
# print(msv4_name,generic_name,field_xds[generic_name].data.shape,field_xds[generic_name].data)
|
|
971
|
-
|
|
972
|
-
# field_and_source_xds[msv4_name] = xr.DataArray.from_dict(
|
|
973
|
-
# {
|
|
974
|
-
# "dims": dims,
|
|
975
|
-
# "data": list(field_xds[generic_name].data),
|
|
976
|
-
# "attrs": msv4_measure,
|
|
977
|
-
# }
|
|
978
|
-
# )
|
|
979
|
-
|
|
980
|
-
# field_measures_type = "sky_coord"
|
|
981
|
-
# field_and_source_xds[msv4_name].attrs["type"] = field_measures_type
|
|
982
|
-
|
|
983
|
-
# field_and_source_xds = field_and_source_xds.assign_coords(coords)
|
|
984
|
-
# if "time" in field_and_source_xds:
|
|
985
|
-
# time_column_description = field_xds.attrs["other"]["msv2"]["ctds_attrs"][
|
|
986
|
-
# "column_descriptions"
|
|
987
|
-
# ]["TIME"]
|
|
988
|
-
# time_msv4_measure = column_description_casacore_to_msv4_measure(
|
|
989
|
-
# time_column_description
|
|
990
|
-
# )
|
|
991
|
-
# field_and_source_xds.coords["time"].attrs.update(time_msv4_measure)
|
|
992
|
-
|
|
993
897
|
return (
|
|
994
898
|
field_and_source_xds,
|
|
995
899
|
ephemeris_path,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import toolviper.utils.logger as logger
|
|
2
1
|
from xradio._utils.schema import column_description_casacore_to_msv4_measure
|
|
3
2
|
|
|
4
3
|
col_to_data_variable_names = {
|
|
@@ -39,6 +38,6 @@ def create_attribute_metadata(col, main_column_descriptions):
|
|
|
39
38
|
if col in ["DATA", "CORRECTED_DATA", "WEIGHT"]:
|
|
40
39
|
if not attrs_metadata:
|
|
41
40
|
attrs_metadata["type"] = "quanta"
|
|
42
|
-
attrs_metadata["units"] =
|
|
41
|
+
attrs_metadata["units"] = "unkown"
|
|
43
42
|
|
|
44
43
|
return attrs_metadata
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import xarray as xr
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
try:
|
|
5
|
+
from casacore import tables
|
|
6
|
+
except ImportError:
|
|
7
|
+
import xradio._utils._casacore.casacore_from_casatools as tables
|
|
8
|
+
|
|
5
9
|
import toolviper.utils.logger as logger
|
|
6
10
|
|
|
7
11
|
from .subtables import subt_rename_ids
|
|
8
12
|
from ._tables.read import load_generic_table, convert_casacore_time
|
|
9
|
-
from xradio._utils.list_and_array import check_if_consistent
|
|
13
|
+
from xradio._utils.list_and_array import check_if_consistent
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
def create_info_dicts(
|
|
@@ -43,12 +47,13 @@ def create_info_dicts(
|
|
|
43
47
|
info dicts ready to be used to update the attrs of the MSv4
|
|
44
48
|
"""
|
|
45
49
|
|
|
46
|
-
if "line_name" in field_and_source_xds.coords:
|
|
47
|
-
line_name = to_list(unique_1d(np.ravel(field_and_source_xds.line_name.values)))
|
|
48
|
-
else:
|
|
49
|
-
line_name = []
|
|
50
|
-
|
|
51
50
|
info_dicts = {}
|
|
51
|
+
|
|
52
|
+
# if "line_name" in field_and_source_xds.coords:
|
|
53
|
+
# line_name = to_list(unique_1d(np.ravel(field_and_source_xds.line_name.values)))
|
|
54
|
+
# else:
|
|
55
|
+
# line_name = []
|
|
56
|
+
|
|
52
57
|
# info_dicts["partition_info"] = {
|
|
53
58
|
# # "spectral_window_id": xds.frequency.attrs["spectral_window_id"],
|
|
54
59
|
# "spectral_window_name": xds.frequency.attrs["spectral_window_name"],
|
|
@@ -121,7 +126,7 @@ def create_observation_info(in_file: str, observation_id: int):
|
|
|
121
126
|
exec_block_xds = load_generic_table(in_file, "ASDM_EXECBLOCK")
|
|
122
127
|
except ValueError as exc:
|
|
123
128
|
logger.debug(
|
|
124
|
-
"Did not find the ASDM_EXECBLOCK subtable, not loading optional fields in observation_info"
|
|
129
|
+
f"Did not find the ASDM_EXECBLOCK subtable, not loading optional fields in observation_info. Exception: {exc}"
|
|
125
130
|
)
|
|
126
131
|
if exec_block_xds:
|
|
127
132
|
exec_block_info = extract_exec_block_info(exec_block_xds)
|