API reference

This API reference spans three pages — this one, part 2 (writing / editing / concurrency / the query engine / primary beams), and Measures — split apart to stay under Documenter's HTML size limit; the search index above covers all three.

BFloat16 is re-exported from BFloat16s.jl so that readtable(ms; precision = BFloat16) works after using MeasurementSets.

Opening tables

MeasurementSets.readtable — Function
readtable(path) -> Table | RefTable | ConcatTable

Read the metadata (description, keywords, data-manager bindings, row count) of the casacore table directory at path. Column data is not read.

Returns a RefTable or ConcatTable when path is a reference / concatenation table (its parent(s) are opened recursively); otherwise a plain Table.

precision controls the in-memory element type of TpFloat / TpComplex columns (the on-disk Float32 / ComplexF32 bytes are never changed; Float64 / ComplexF64 / Bool are never narrowed):

valueeffect
nothing (default):half for a MAIN table (table.info Type "Measurement Set"), :full otherwise
:halfnarrow TpComplex only → ComplexF16 (DATA, …); TpFloat stays Float32 (real WEIGHT values exceed Float16's 65504 range)
:full / Float32no narrowing
Float16narrow every TpFloat→Float16, TpComplex→ComplexF16 (a large WEIGHT will overflow to Inf — caller's risk)
BFloat16narrow every TpFloat→BFloat16, TpComplex→Complex{BFloat16} (BFloat16 has Float32's exponent range — overflow-safe, and its 7-bit mantissa matches 8-bit-derived data)

Override per column with column(t, name; precision=…).

A shared (read) lock on <path>/table.lock is held only while table.dat is slurped; the row count then comes from the table.lock sync blob when present (as casacore does), else from table.dat. The lazy storage-manager reads that a later column() triggers are not locked – they rely on the writers' atomic renames.

source
MeasurementSets.MeasurementSet — Type
MeasurementSet(path; precision=nothing) -> MeasurementSet

Open the MAIN table of a Measurement Set directory and read its metadata. Subtables are read on first access via getproperty / subtable.

precision is forwarded to readtable for the MAIN table (:half — the default — reads DATA etc. as ComplexF16; :full, Float16 and BFloat16 also accepted). Subtables always open at :full.

source

Table types

MeasurementSets.AbstractTable — Type

Common supertype of the casacore table kinds this package can read: Table (a plain table), RefTable (a row-number reference into a parent table), and ConcatTable (a virtual row-wise concatenation of same-schema tables). All three answer nrow / columnnames / columndesc / keywords / subtables / column and interoperate with Tables.jl.

source
MeasurementSets.Table — Type
Table <: AbstractTable

A plain on-disk casacore table, as returned by readtable for a table.dat of subtype "PlainTable" (the MS MAIN table and every standard subtable). Column data is read lazily and on demand through the bound storage managers; cell reads go through column / getcell / t[:NAME]. See also RefTable and ConcatTable for the reference / concatenation kinds, and edit to open one for update.

precision (:half / :full / Float16 / BFloat16) — see readtable.

source
MeasurementSets.RefTable — Type

A casacore RefTable: a persistent row-number reference into a parent table (what a TaQL SELECT ... GIVING '<path>' row selection or table.query writes). Stores no cell data of its own — every read delegates to parent through rows (1-based parent row per ref row).

source
MeasurementSets.ConcatTable — Type

A casacore ConcatTable: a virtual row-wise concatenation of parts (same-schema tables — e.g. the MAIN table of a MultiMS). offsets is the cumulative row map (length(parts)+1 entries, offsets[end] = total rows). Stores no cell data of its own.

source
MeasurementSets.GroupedTable — Type
GroupedTable

An in-memory columnar table — the result of groupby, join, or query on one of those. It is a full AbstractTable (so it chains back into query / groupby / join) and a Tables.jl source. Access columns with gt.OUTNAME, gt["OUTNAME"], column(gt, "OUTNAME"), DataFrame(gt), or persist with write_table(dst, "T", gt; nrow=nrow(gt)).

names and cols are reserved field names (reached via getfield); a column literally named names / cols is accessible only through gt["names"] / column(gt, "cols").

source

Columns and data

MeasurementSets.column — Function
column(t::Table, name; precision=nothing) -> Column

A lazy AbstractVector over a column: col[i] reads one cell, col[r] a range, col[:] the whole column (fast path).

precision (nothing follows t.precision; otherwise :half / :full / Float16 / BFloat16 / Float32 — see readtable): :half narrows only a TpComplex column (to ComplexF16); Float16 / BFloat16 narrow any Float32 / ComplexF32 column to that scalar type / its Complex; :full keeps the column wide.

source
column(ms, sub, name; precision=nothing) -> Column

A lazy AbstractVector over subtable sub's column name (a MeasurementSet convenience for column(subtable(ms, sub), name; precision)) — completes the getcolumn(ms, sub, name) / getcell(ms, sub, name, row) family with the lazy verb they're both built on, found missing in the same sweep.

source
MeasurementSets.Column — Type
Column{T} <: AbstractVector{T}

A lazy view of one table column, returned by column and t[:NAME]. Indexing reads on demand: col[i] fetches one cell, col[:] takes the storage manager's whole-column fast path, col[r] a row subset. T is the best-known element type — a scalar, a fixed-shape Array{E,N}, or Array{E} when the rank is only known once a cell is read.

source
MeasurementSets.getcolumn — Method
getcolumn(t, name; precision=nothing) -> Vector / Vector{Array}

Read an entire column's data (eager; equivalent to column(t, name; precision)[:]).

source
MeasurementSets.getcell — Method
getcell(t, name, row; precision=nothing) -> value

Read one cell (row is 1-based).

Each call resolves name to a Column (a columndesc lookup + opening/looking up the bound data-manager instance), which in a for row in ...; getcell(t, name, row); end loop used to dominate the actual per-cell read cost – it no longer does for a plain Table (Phase 426: the Column is kept with the table, so a repeated getcell costs about a cached column(t, name)[row] plus a dictionary lookup, ~40 ns instead of ~470 ns); other table kinds (RefTable, ConcatTable, ...) still resolve the name on every call, so for those cache the lazy column once and index into that: col = column(t, name); for row in ...; col[row]; end.

source
MeasurementSets.BlockColumn — Type
BlockColumn{T,N} <: AbstractVector{AbstractArray{T,N}}

The lazy whole-column return value of a fixed-shape array column's bulk read (Phase 236) — SSM- or TiledStMan-backed columns like UVW, DATA, or FLAG. Every row's cell shares ONE backing buffer built up front; getindex computes that row's reshape(view(...)) on demand instead of building nrow such wrapper objects eagerly (Phase 234/235's own fix already made each data manager build the shared buffer, but still wrapped it into an eager Vector of nrow view objects — the BlockColumn here is stored instead, with no further per-row cost until something actually indexes it).

Behaves like any other AbstractVector — every existing consumer (Tables.jl, the TaQL engine, edit.jl, copyms) already treats a column's [:] result as an opaque AbstractVector of AbstractArray cells (TiledStMan's narrow-precision bulk path has returned non-Array-typed view wrappers since Phase 35/68), so this is a drop-in, non-breaking change to what getcolumn/column(t,name)[:] already returned. collect(col) (or Array.(col)) forces genuine per-row materialisation when an owned copy is actually needed — exactly what _read_cells (create.jl, used by copyms/copytable) already does for every array-cell column, lazy or not.

rawblock exposes the underlying buffer directly as one real (cellshape..., nrow) Array, with NO per-row indirection at all, for a caller doing a bulk numeric operation across the whole column.

source
MeasurementSets.rawblock — Function
rawblock(t, name; precision=nothing) -> Array

The raw (cellshape..., nrow) block underlying a fixed-shape array column's bulk read — the SAME buffer column(t, name)[:] (a BlockColumn) lazily slices per row, exposed directly with NO per-row indirection at all (size(result) == (cellshape..., nrow), zero-copy reshape). Only a fixed-shape SSM/TiledStMan array column (DATA, FLAG, UVW, a subtable's POSITION, …) has a block representation — a scalar column or a variable-shape/indirect array column (CHAN_FREQ, …) raises a clear ArgumentError.

source

Physical units

import Unitful, UnitfulAngles, UnitfulAstro gives these real methods (see Concepts).

MeasurementSets.columnunit — Function
columnunit(t, name) -> Unitful.Units | Tuple | nothing

The physical unit of column name, from its QuantumUnits keyword, as a Unitful unit. nothing when the column has no unit keyword; a Tuple for a genuinely mixed-unit column. Needs the Unitful extension — import Unitful, UnitfulAngles, UnitfulAstro.

source
MeasurementSets.qcolumn — Function
qcolumn(t, name; precision=nothing) -> Vector

The whole column with its unit attached as Unitful quantities (materialised, not a lazy Column). A unitless column is returned unchanged. Needs the Unitful extension.

source
MeasurementSets.UNITS_NO_JULIA_COUNTERPART — Constant
UNITS_NO_JULIA_COUNTERPART

casacore units that no third-party Julia package (Unitful / UnitfulAngles / UnitfulAstro) implements, and how MeasurementSets handles each:

  • :pseudo — registered as a dimensionless unit by the Unitful extension (so Jy/beam parses to Jy beam⁻¹, dimensionally Jy).
  • :nounits — mapped to Unitful.NoUnits (casacore's canonical dimensionless markers).
  • :unsupported — raises a clear error; use the suggested replacement.
  • :dimension — exists in Unitful but with a different dimension than casacore (casacore treats it as a base dimension).
source

Reference frames (measures)

import SOFA (and optionally EarthOrientation) activates measconvert; see Concepts. Split onto its own page — Measures — since this category alone (measure types, measconvert, and ~50 reference-frame singleton types) is large enough to push the combined API page past Documenter's HTML size limit.

Schema and metadata

MeasurementSets.columndesc — Function
columndesc(t, name) -> ColumnDesc

The ColumnDesc (type, cell shape, keywords, storage-manager binding) for column name of table t. Throws KeyError if there is no such column. The keyword record of the result is a copy: changing an array inside it does not change the table.

source
MeasurementSets.ColumnDesc — Type
ColumnDesc

Description of one table column: its name, element type (a CasaType), cell shape (a CellShape — () scalar, a Dims tuple, VariableShape, or VariableDims), comment, per-column keywords (a Record, holding units / MEASINFO / engine config), and the storage-manager manager type + group (instance) it is bound to. Obtained from columndesc; the fields are read-only.

source
MeasurementSets.keywords — Function
keywords(t) -> Record

The table-level keyword set of t as a Record (MS_VERSION, MEASURE_REFERENCE, subtable references, …). Per-column keywords live on columndesc(t, name).keywords. The result is a copy: changing an array inside it does not change the table.

source
MeasurementSets.subtables — Function
subtables(t::Table) -> Vector{Pair{String,String}}

Keyword name => subtable directory path, for every TpTable keyword.

source
MeasurementSets.CasaType — Type
CasaType

Enum mirroring casacore's DataType — the element type of a column or keyword value (TpBool, TpInt, TpFloat, TpComplex, TpString, the TpArray* variants, TpInt64, …). It is the type field of a ColumnDesc; juliatype(t) gives the corresponding Julia type.

source
MeasurementSets.CellShape — Type

Cell-shape descriptor for a column:

  • () — scalar
  • a Dims tuple — array with a fixed cell shape
  • VariableShape — array, fixed dimensionality, per-row-variable shape
  • VariableDims — array whose dimensionality itself varies per row
source
MeasurementSets.VariableShape — Type

An array column with a fixed number of axes but a per-row-variable cell shape (casacore ndim > 0 with no declared shape, e.g. DATA, FLAG_CATEGORY). ndim is that number of axes when known (a column read from disk always knows it) and 0 when not (VariableShape(), e.g. one inferred from data – which cannot know it for a zero-row column).

source

The standard schema

MeasurementSets.stdcolumns — Function
stdcolumns(name) -> Vector{StdColumn}

The standard-schema columns of MS v2 table name — shorthand for stdtable(name).columns (a copy, so the schema cannot be changed through it).

source
MeasurementSets.validate — Function
validate(t::AbstractTable; table="MAIN") -> Vector{String}

Check t against the standard schema for table. Returns a list of issues (missing required column, element-type mismatch, missing required subtable, unexpected keyword value); empty means conformant. Never throws.

source
validate(ms::MeasurementSet) -> Vector{String}

Validate MAIN and every present standard subtable.

source

Writing / editing / concurrency / the query engine / primary beams are on a second page — API reference (part 2) — split off to stay under Documenter's HTML size limit.