xarray-ms 0.3.8__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.github/workflows/ci.yml +3 -3
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.github/workflows/pre-commit.yml +1 -1
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/PKG-INFO +1 -1
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/changelog.rst +14 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/conf.py +1 -1
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/install.rst +16 -28
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/pyproject.toml +2 -2
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/factories/correlated.py +2 -2
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/measures_adapters.py +36 -33
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/measures_encoders.py +2 -17
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/errors.py +1 -1
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.github/ISSUE_TEMPLATE.md +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.github/dependabot.yml +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.github/workflows/readthedocs.yml +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.gitignore +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.pre-commit-config.yaml +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/.readthedocs.yaml +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/LICENSE +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/README.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/Makefile +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/make.bat +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/api.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/index.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/introduction.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/links.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/partitioning.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/roadmap.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/doc/source/tutorial.rst +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/hello.txt +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/__init__.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/conftest.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/msv4_test_corpus/__init__.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/msv4_test_corpus/conftest.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/msv4_test_corpus/test_msv_corpus.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_antenna.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_backend.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_basic.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_field_and_source.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_github.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_imputation.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_measures.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_multiton.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_read.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_structure.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_utils.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/tests/test_zarr_roundtrip.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/__init__.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/array.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/entrypoint.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/entrypoint_utils.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/factories/__init__.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/factories/antenna.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/factories/core.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/factories/field_and_source.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/imputation.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/partition.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/structure.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/backend/msv2/table_utils.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/casa_types.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/msv4_types.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/multiton.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/query.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/testing/__init__.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/testing/simulator.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/testing/utils.py +0 -0
- {xarray_ms-0.3.8 → xarray_ms-0.5.0}/xarray_ms/utils.py +0 -0
|
@@ -74,7 +74,7 @@ jobs:
|
|
|
74
74
|
python-version: ${{ matrix.python-version }}
|
|
75
75
|
|
|
76
76
|
- name: Checkout source
|
|
77
|
-
uses: actions/checkout@
|
|
77
|
+
uses: actions/checkout@v6
|
|
78
78
|
with:
|
|
79
79
|
fetch-depth: 1
|
|
80
80
|
|
|
@@ -83,7 +83,7 @@ jobs:
|
|
|
83
83
|
|
|
84
84
|
- name: Load cached MSv4 Test Corpus
|
|
85
85
|
id: load-cached-msv4-test-corpus
|
|
86
|
-
uses: actions/cache@
|
|
86
|
+
uses: actions/cache@v5
|
|
87
87
|
with:
|
|
88
88
|
key: msv4-test-corpus-${{ hashFiles('metadata.json')}}
|
|
89
89
|
path: ~/.cache/xarray-ms/msv4-test-data
|
|
@@ -123,7 +123,7 @@ jobs:
|
|
|
123
123
|
python-version: 3.11
|
|
124
124
|
|
|
125
125
|
- name: Checkout source
|
|
126
|
-
uses: actions/checkout@
|
|
126
|
+
uses: actions/checkout@v6
|
|
127
127
|
with:
|
|
128
128
|
fetch-depth: 1
|
|
129
129
|
|
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
Changelog
|
|
4
4
|
=========
|
|
5
5
|
|
|
6
|
+
0.5.0 (02-03-2026)
|
|
7
|
+
------------------
|
|
8
|
+
* Fix ``VisibilityCoder`` typo (:pr:`145`)
|
|
9
|
+
* Raise an exception if no MSv4 Frame Type is available in ``EpochCoder.decode`` (:pr:`145`)
|
|
10
|
+
* Replace an assert with an ``InvalidMeasurementSet`` exception if the
|
|
11
|
+
number of ``TabRefTypes`` doesn't match the ``TabRefCodes`` (:pr:`145`)
|
|
12
|
+
* Guard frame inference in a dictionary with a KeyError (:pr:`145`)
|
|
13
|
+
|
|
14
|
+
0.3.9 (18-02-2026)
|
|
15
|
+
------------------
|
|
16
|
+
* Define and use an ``OnMissingLiteralType`` (:pr:`144`)
|
|
17
|
+
* Correct exception name from ComplexMeasuremetSet to ComplexMeasurementSet (:pr:`143`)
|
|
18
|
+
* Remove poetry-specific installation documentation (:pr:`140`)
|
|
19
|
+
|
|
6
20
|
0.3.8 (17-10-2025)
|
|
7
21
|
------------------
|
|
8
22
|
* Synchronise with v4.0.0 schema version (:pr:`139`)
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
project = "xarray-ms"
|
|
12
12
|
copyright = "2024 - 2025 NRF (SARAO) and Rhodes University (RATT) Centre"
|
|
13
13
|
author = "Simon Perkins"
|
|
14
|
-
release = "0.
|
|
14
|
+
release = "0.5.0"
|
|
15
15
|
|
|
16
16
|
# -- General configuration ---------------------------------------------------
|
|
17
17
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
@@ -16,40 +16,31 @@ they must be installed separately.
|
|
|
16
16
|
Development
|
|
17
17
|
===========
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.. _poetry: https://python-poetry.org/
|
|
22
|
-
|
|
23
|
-
Then, the following commands will install the required dependencies,
|
|
24
|
-
optional testing dependencies, documentation and development dependencies
|
|
25
|
-
in a suitable virtual environment:
|
|
19
|
+
Create a virtual environment and install with the dev, doc and testing
|
|
20
|
+
dependencies:
|
|
26
21
|
|
|
27
22
|
.. code-block:: bash
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
$
|
|
31
|
-
$
|
|
32
|
-
$
|
|
33
|
-
$ poetry shell
|
|
24
|
+
|
|
25
|
+
$ virtualenv -p python3.12 /tmp/xms
|
|
26
|
+
$ source xms/bin/activate
|
|
27
|
+
(xms) $ pip install -e .[dev,doc,testing]
|
|
34
28
|
|
|
35
29
|
The pre-commit hooks can be manually executed as follows:
|
|
36
30
|
|
|
37
31
|
.. code-block:: bash
|
|
38
32
|
|
|
39
|
-
$
|
|
40
|
-
|
|
33
|
+
(xms) $ pre-commit run -a
|
|
41
34
|
|
|
42
35
|
Test Suite
|
|
43
36
|
----------
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
execute the test suite
|
|
38
|
+
After creating the virtual environment above, run the following command
|
|
39
|
+
within the xarray-ms source code directory to execute the test suite:
|
|
47
40
|
|
|
48
41
|
.. code-block:: bash
|
|
49
42
|
|
|
50
|
-
$
|
|
51
|
-
$ poetry install -E testing --with dev
|
|
52
|
-
$ poetry run py.test -s -vvv tests/
|
|
43
|
+
(xms) $ py.test -s -vvv tests/
|
|
53
44
|
|
|
54
45
|
|
|
55
46
|
Documentation
|
|
@@ -60,15 +51,8 @@ build the Sphinx documentation
|
|
|
60
51
|
|
|
61
52
|
.. code-block:: bash
|
|
62
53
|
|
|
63
|
-
$ cd
|
|
64
|
-
$
|
|
65
|
-
$ poetry shell
|
|
66
|
-
$ cd doc
|
|
67
|
-
$ make html
|
|
68
|
-
|
|
69
|
-
.. _cubed: https://cubed-dev.github.io/cubed/
|
|
70
|
-
.. _dask: https://www.dask.org/
|
|
71
|
-
.. _zarr: https://zarr.dev/
|
|
54
|
+
(xms) $ cd doc
|
|
55
|
+
(xms) $ make html
|
|
72
56
|
|
|
73
57
|
Release Process
|
|
74
58
|
---------------
|
|
@@ -88,3 +72,7 @@ on the ``main`` branch:
|
|
|
88
72
|
.. code-block:: bash
|
|
89
73
|
|
|
90
74
|
$ tbump 0.2.0
|
|
75
|
+
|
|
76
|
+
.. _cubed: https://cubed-dev.github.io/cubed/
|
|
77
|
+
.. _dask: https://www.dask.org/
|
|
78
|
+
.. _zarr: https://zarr.dev/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "xarray-ms"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
4
4
|
description = "xarray MSv4 views over MSv2 Measurement Sets"
|
|
5
5
|
authors = [{name = "Simon Perkins", email = "simon.perkins@gmail.com"}]
|
|
6
6
|
readme = "README.rst"
|
|
@@ -54,7 +54,7 @@ extend-select = ["I"]
|
|
|
54
54
|
# github_url = "https://github.com/<user or organization>/<project>/"
|
|
55
55
|
|
|
56
56
|
[tool.tbump.version]
|
|
57
|
-
current = "0.
|
|
57
|
+
current = "0.5.0"
|
|
58
58
|
|
|
59
59
|
# Example of a semver regexp.
|
|
60
60
|
# Make sure this matches current_version before
|
|
@@ -23,7 +23,7 @@ from xarray_ms.backend.msv2.imputation import (
|
|
|
23
23
|
from xarray_ms.backend.msv2.measures_encoders import (
|
|
24
24
|
MSv2Coder,
|
|
25
25
|
MSv2CoderFactory,
|
|
26
|
-
|
|
26
|
+
VisibilityCoder,
|
|
27
27
|
)
|
|
28
28
|
from xarray_ms.backend.msv2.structure import MSv2StructureFactory, PartitionKeyT
|
|
29
29
|
from xarray_ms.casa_types import ColumnDesc, Polarisations
|
|
@@ -57,7 +57,7 @@ MSV4_to_MSV2_COLUMN_SCHEMAS = {
|
|
|
57
57
|
),
|
|
58
58
|
"FLAG": MSv2ColumnSchema("FLAG", ("frequency", "polarization"), 1, None),
|
|
59
59
|
"VISIBILITY": MSv2ColumnSchema(
|
|
60
|
-
"DATA", ("frequency", "polarization"), np.nan + np.nan * 1j,
|
|
60
|
+
"DATA", ("frequency", "polarization"), np.nan + np.nan * 1j, VisibilityCoder()
|
|
61
61
|
),
|
|
62
62
|
"WEIGHT_ROW": MSv2ColumnSchema(
|
|
63
63
|
"WEIGHT",
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import typing
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
-
from typing import TYPE_CHECKING, Any, Dict, Literal, Sequence, overload
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, Literal, Sequence, get_args, overload
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
|
|
@@ -17,7 +17,7 @@ from xarray_ms.casa_types import (
|
|
|
17
17
|
UvwMeasures,
|
|
18
18
|
)
|
|
19
19
|
from xarray_ms.errors import (
|
|
20
|
-
|
|
20
|
+
ComplexMeasurementSet,
|
|
21
21
|
InvalidMeasurementSet,
|
|
22
22
|
MissingMeasuresInfo,
|
|
23
23
|
MissingQuantumUnits,
|
|
@@ -28,6 +28,8 @@ from xarray_ms.errors import (
|
|
|
28
28
|
if TYPE_CHECKING:
|
|
29
29
|
import pyarrow as pa
|
|
30
30
|
|
|
31
|
+
OnMissingType = Literal["none", "raise"]
|
|
32
|
+
|
|
31
33
|
|
|
32
34
|
@dataclass
|
|
33
35
|
class MeasuresData:
|
|
@@ -45,9 +47,9 @@ CASA_MEASURES_MAP = {
|
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
|
|
48
|
-
def raise_invalid_on_missing(on_missing:
|
|
49
|
-
if on_missing not in
|
|
50
|
-
raise ValueError(f"'on_missing' {on_missing} not in {
|
|
50
|
+
def raise_invalid_on_missing(on_missing: OnMissingType):
|
|
51
|
+
if on_missing not in get_args(OnMissingType):
|
|
52
|
+
raise ValueError(f"'on_missing' {on_missing} not in {get_args(OnMissingType)}")
|
|
51
53
|
|
|
52
54
|
|
|
53
55
|
def raise_on_measinfo_indirection(column_name: str, measinfo: Dict[str, Any]):
|
|
@@ -57,19 +59,8 @@ def raise_on_measinfo_indirection(column_name: str, measinfo: Dict[str, Any]):
|
|
|
57
59
|
i.e. if it has a ``VarRefCol`` for defining a per-row frame or
|
|
58
60
|
``RefOff*`` keywords for defining offsets.
|
|
59
61
|
"""
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for k in measinfo:
|
|
63
|
-
if "VarRefCol" in k:
|
|
64
|
-
return True
|
|
65
|
-
|
|
66
|
-
if k.startswith("RefOff"):
|
|
67
|
-
return True
|
|
68
|
-
|
|
69
|
-
return False
|
|
70
|
-
|
|
71
|
-
if check():
|
|
72
|
-
raise ComplexMeasuremetSet(
|
|
62
|
+
if any("VarRefCol" in k or k.startswith("RefOff") for k in measinfo):
|
|
63
|
+
raise ComplexMeasurementSet(
|
|
73
64
|
f"The MEASINFO in column {column_name} {measinfo} "
|
|
74
65
|
f"contains indirection in the form of `VarRefCol` "
|
|
75
66
|
f"or `RefCol*` entries. "
|
|
@@ -93,7 +84,7 @@ class MeasuresMixin:
|
|
|
93
84
|
) -> Dict[str, Any]: ...
|
|
94
85
|
|
|
95
86
|
def extract_measinfo(
|
|
96
|
-
self, column_desc: ColumnDesc, on_missing:
|
|
87
|
+
self, column_desc: ColumnDesc, on_missing: OnMissingType = "none"
|
|
97
88
|
) -> Dict[str, Any] | None:
|
|
98
89
|
"""Extracts the MEASINFO keyword from the column descriptor, if present"""
|
|
99
90
|
try:
|
|
@@ -118,7 +109,7 @@ class MeasuresMixin:
|
|
|
118
109
|
) -> str: ...
|
|
119
110
|
|
|
120
111
|
def extract_quantum_unit(
|
|
121
|
-
self, column_desc: ColumnDesc, on_missing:
|
|
112
|
+
self, column_desc: ColumnDesc, on_missing: OnMissingType = "none"
|
|
122
113
|
) -> str | None:
|
|
123
114
|
"""Attempts to extract a single quantum unit from the keywords
|
|
124
115
|
of the column descriptor.
|
|
@@ -164,7 +155,7 @@ class MeasuresMixin:
|
|
|
164
155
|
) -> str: ...
|
|
165
156
|
|
|
166
157
|
def extract_msv2_type(
|
|
167
|
-
self, column_desc: ColumnDesc, on_missing:
|
|
158
|
+
self, column_desc: ColumnDesc, on_missing: OnMissingType = "none"
|
|
168
159
|
) -> str | None:
|
|
169
160
|
"""Returns the msv2 measures type, derived from the 'type' keyword
|
|
170
161
|
in the column descriptor keywords"""
|
|
@@ -202,7 +193,7 @@ class MeasuresMixin:
|
|
|
202
193
|
) -> str: ...
|
|
203
194
|
|
|
204
195
|
def extract_msv4_type(
|
|
205
|
-
self, column_desc: ColumnDesc, on_missing:
|
|
196
|
+
self, column_desc: ColumnDesc, on_missing: OnMissingType = "none"
|
|
206
197
|
) -> str | None:
|
|
207
198
|
"""Returns the msv4 measures type, derived from the 'type' keyword
|
|
208
199
|
in the column descriptor keywords"""
|
|
@@ -249,26 +240,26 @@ class AbstractMeasuresAdapter(ABC):
|
|
|
249
240
|
def msv2_frame(self, on_missing: Literal["raise"]) -> str: ...
|
|
250
241
|
|
|
251
242
|
@abstractmethod
|
|
252
|
-
def msv2_frame(self, on_missing:
|
|
243
|
+
def msv2_frame(self, on_missing: OnMissingType = "none") -> str | None:
|
|
253
244
|
"""Returns the MSv2 Measures frame.
|
|
254
245
|
|
|
255
246
|
This corresponds to ``MEASINFO['Ref']`` or possibly ``MEASINFO['VarRefCol']``"""
|
|
256
247
|
raise NotImplementedError
|
|
257
248
|
|
|
258
249
|
@abstractmethod
|
|
259
|
-
def msv2_type(self, on_missing:
|
|
250
|
+
def msv2_type(self, on_missing: OnMissingType = "none") -> str | None:
|
|
260
251
|
"""Returns the MSv2 Measures type.
|
|
261
252
|
|
|
262
253
|
This corresponds to ``MEASINFO['type']`` in the column descriptor keywords"""
|
|
263
254
|
raise NotImplementedError
|
|
264
255
|
|
|
265
256
|
@abstractmethod
|
|
266
|
-
def msv4_type(self, on_missing:
|
|
257
|
+
def msv4_type(self, on_missing: OnMissingType = "none") -> str | None:
|
|
267
258
|
"""Return the MSv4 Measures type"""
|
|
268
259
|
raise NotImplementedError
|
|
269
260
|
|
|
270
261
|
@abstractmethod
|
|
271
|
-
def quantum_unit(self, on_missing:
|
|
262
|
+
def quantum_unit(self, on_missing: OnMissingType = "none") -> str | None:
|
|
272
263
|
"""Returns a single unit associated with this measure.
|
|
273
264
|
|
|
274
265
|
This corresponds to ``MEASINFO['QuantumUnits']`` in the
|
|
@@ -300,13 +291,13 @@ class ColumnDescMeasuresAdapter(AbstractMeasuresAdapter, MeasuresMixin):
|
|
|
300
291
|
def column_name(self) -> str:
|
|
301
292
|
return self._column_desc.name
|
|
302
293
|
|
|
303
|
-
def quantum_unit(self, on_missing:
|
|
294
|
+
def quantum_unit(self, on_missing: OnMissingType = "none") -> str | None:
|
|
304
295
|
return self.extract_quantum_unit(self._column_desc, on_missing=on_missing)
|
|
305
296
|
|
|
306
|
-
def msv2_type(self, on_missing:
|
|
297
|
+
def msv2_type(self, on_missing: OnMissingType = "none"):
|
|
307
298
|
return self.extract_msv2_type(self._column_desc, on_missing=on_missing)
|
|
308
299
|
|
|
309
|
-
def msv4_type(self, on_missing:
|
|
300
|
+
def msv4_type(self, on_missing: OnMissingType = "none") -> str | None:
|
|
310
301
|
return self.extract_msv4_type(self._column_desc, on_missing=on_missing)
|
|
311
302
|
|
|
312
303
|
@overload
|
|
@@ -315,7 +306,7 @@ class ColumnDescMeasuresAdapter(AbstractMeasuresAdapter, MeasuresMixin):
|
|
|
315
306
|
@overload
|
|
316
307
|
def msv2_frame(self, on_missing: Literal["raise"]) -> str: ...
|
|
317
308
|
|
|
318
|
-
def msv2_frame(self, on_missing:
|
|
309
|
+
def msv2_frame(self, on_missing: OnMissingType = "none") -> str | None:
|
|
319
310
|
if (
|
|
320
311
|
measinfo := self.extract_measinfo(self._column_desc, on_missing=on_missing)
|
|
321
312
|
) is None:
|
|
@@ -359,7 +350,7 @@ class ArrowTableMeasuresAdapter(ColumnDescMeasuresAdapter, MeasuresMixin):
|
|
|
359
350
|
@overload
|
|
360
351
|
def msv2_frame(self, on_missing: Literal["raise"]) -> str: ...
|
|
361
352
|
|
|
362
|
-
def msv2_frame(self, on_missing:
|
|
353
|
+
def msv2_frame(self, on_missing: OnMissingType = "none") -> str | None:
|
|
363
354
|
if (
|
|
364
355
|
measinfo := self.extract_measinfo(self._column_desc, on_missing=on_missing)
|
|
365
356
|
) is None:
|
|
@@ -389,7 +380,11 @@ class ArrowTableMeasuresAdapter(ColumnDescMeasuresAdapter, MeasuresMixin):
|
|
|
389
380
|
# The measures information may contain it's own reference types and codes
|
|
390
381
|
if isinstance(tab_ref_types := measinfo.get("TabRefTypes"), Sequence):
|
|
391
382
|
if isinstance(tab_ref_codes := measinfo.get("TabRefCodes"), Sequence):
|
|
392
|
-
|
|
383
|
+
if len(tab_ref_types) != len(tab_ref_codes):
|
|
384
|
+
raise InvalidMeasurementSet(
|
|
385
|
+
f"TabRefTypes {tab_ref_types} and TabRefCodes {tab_ref_codes} "
|
|
386
|
+
f"have different lengths in {self.column_name} MEASINFO"
|
|
387
|
+
)
|
|
393
388
|
else:
|
|
394
389
|
tab_ref_codes = [MeasuresEnum[t].value for t in tab_ref_types]
|
|
395
390
|
|
|
@@ -399,7 +394,15 @@ class ArrowTableMeasuresAdapter(ColumnDescMeasuresAdapter, MeasuresMixin):
|
|
|
399
394
|
code_frame_map = {m.value: m.name for m in MeasuresEnum}
|
|
400
395
|
|
|
401
396
|
# Try and find a unique frame
|
|
402
|
-
|
|
397
|
+
try:
|
|
398
|
+
frames = {code_frame_map[c] for c in var_ref_col}
|
|
399
|
+
except KeyError as e:
|
|
400
|
+
raise InvalidMeasurementSet(
|
|
401
|
+
f"Code {e.args[0]} in {var_ref_col_name} is not in the "
|
|
402
|
+
f"code frame map {code_frame_map} for column {self.column_name}"
|
|
403
|
+
) from e
|
|
404
|
+
|
|
405
|
+
if len(frames) == 0:
|
|
403
406
|
return None
|
|
404
407
|
|
|
405
408
|
if len(frames) > 1:
|
|
@@ -107,21 +107,6 @@ class MeasuresCoder(MSv2Coder):
|
|
|
107
107
|
self.measures_adapter = measures_adapter
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
class QuantityCoder(MeasuresCoder):
|
|
111
|
-
"""Encodes a quantum unit"""
|
|
112
|
-
|
|
113
|
-
def encode(self, variable: Variable, name: T_Name = None) -> Variable:
|
|
114
|
-
dims, data, attrs, encoding = unpack_for_encoding(variable)
|
|
115
|
-
attrs = {k: v for k, v in attrs.items() if k not in {"type", "units"}}
|
|
116
|
-
return Variable(dims, data, attrs, encoding, fastpath=True)
|
|
117
|
-
|
|
118
|
-
def decode(self, variable: Variable, name: T_Name = None) -> Variable:
|
|
119
|
-
dims, data, attrs, encoding = unpack_for_decoding(variable)
|
|
120
|
-
attrs["type"] = "quantity"
|
|
121
|
-
attrs["units"] = self.measures_adapter.quantum_unit("raise")
|
|
122
|
-
return Variable(dims, data, attrs, encoding, fastpath=True)
|
|
123
|
-
|
|
124
|
-
|
|
125
110
|
class SuppliedAttributesCoder(MSv2Coder):
|
|
126
111
|
"""Adds and removes the supplied attributes during decoding and encoding"""
|
|
127
112
|
|
|
@@ -149,7 +134,7 @@ class SuppliedQuantityCoder(SuppliedAttributesCoder):
|
|
|
149
134
|
super().__init__({"type": "quantity", "units": units})
|
|
150
135
|
|
|
151
136
|
|
|
152
|
-
class
|
|
137
|
+
class VisibilityCoder(SuppliedQuantityCoder):
|
|
153
138
|
"""Visibility coder"""
|
|
154
139
|
|
|
155
140
|
def __init__(self):
|
|
@@ -227,7 +212,7 @@ class EpochCoder(MeasuresCoder):
|
|
|
227
212
|
|
|
228
213
|
def decode(self, variable: Variable, name: T_Name = None) -> Variable:
|
|
229
214
|
dims, data, attrs, encoding = unpack_for_decoding(variable)
|
|
230
|
-
attrs["type"] = self.measures_adapter.msv4_type()
|
|
215
|
+
attrs["type"] = self.measures_adapter.msv4_type("raise")
|
|
231
216
|
attrs["units"] = self.measures_adapter.quantum_unit("raise")
|
|
232
217
|
attrs["format"] = "unix"
|
|
233
218
|
if (msv2_frame := self.measures_adapter.msv2_frame("raise")) == "UTC":
|
|
@@ -39,7 +39,7 @@ class InvalidMeasurementSet(ValueError):
|
|
|
39
39
|
"""Raised when the Measurement Set is invalid in some way"""
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
class
|
|
42
|
+
class ComplexMeasurementSet(ValueError):
|
|
43
43
|
"""Raised when complexity in the Measurement Set prevents processing"""
|
|
44
44
|
|
|
45
45
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|