SOFA

class hrtfpykit.sofa.SOFA

Bases: object

Represent a SOFA file and its netCDF4 storage handle.

SOFA is the library abstraction around an open netCDF4 object that follows a SOFA convention. It provides controlled access to dimensions, global attributes, variables, and variable attributes through hrtfpykit collection wrappers, plus explicit methods for creating, modifying, cloning, saving, and summarizing SOFA files.

The class is used directly for SOFA inspection workflows and indirectly by HRTF, where it acts as the persistence layer for HRIR/HRTF data, source positions, sampling metadata, and convention metadata.

Notes

No hidden I/O is performed. Files are only read or written when you call load_sofa(), save(), or other explicit editing methods. The underlying storage object is a netCDF4 Dataset, so standard netCDF4 rules and constraints apply. Methods that mutate SOFA content require a writable netCDF4 handle; the safest workflow is to call clone() or copy_with(), modify the in-memory copy, then save the result explicitly.

netCDF4_dataset

Open netCDF4 storage handle backing this SOFA object. None means no SOFA file has been loaded or created.

Type:

netCDF4.Dataset | None

path

Original or most recent disk path associated with the SOFA object. In-memory clones start with None.

Type:

pathlib.Path | None

Examples

Load a SOFA file and access its main metadata and array collections through a SOFA object:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> sofa.path.name
'P0001_FreeFieldComp_44kHz.sofa'
>>> sofa.Dimensions.get("M").value
793
>>> sofa.Dimensions.get("R").value
2
>>> sofa.Dimensions.get("N").value
256
>>> sofa.GlobalAttributes.get("SOFAConventions").value
'SimpleFreeFieldHRIR'
>>> sofa.VariableAttributes.get("SourcePosition:Type").value
'spherical'
>>> sofa.Variables.get("Data.IR").value.shape
(793, 2, 256)
property Dimensions: _Dimensions | None

Return the SOFA dimension collection wrapper.

The wrapper exposes dimension names, sizes, and per-dimension DimensionsWrap objects from the current netCDF4 storage handle.

Returns:

Dimension access wrapper, or None when no SOFA file is loaded.

Return type:

Optional[_Dimensions]

Examples

Inspect the measurement, receiver, and sample dimensions of a loaded SimpleFreeFieldHRIR SOFA file:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> sofa.Dimensions.get("M").value
793
>>> sofa.Dimensions.get("R").value
2
>>> sofa.Dimensions.get("N").value
256
property GlobalAttributes: _GlobalAttributes | None

Return the SOFA global-attribute collection wrapper.

Global attributes include convention metadata such as SOFAConventions, SOFAConventionsVersion, DataType, application metadata, and file lifecycle timestamps.

Returns:

Global-attribute access wrapper, or None when no SOFA file is loaded.

Return type:

Optional[_GlobalAttributes]

Examples

Read convention-level metadata from a loaded SOFA file:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> sofa.GlobalAttributes.get("SOFAConventions").value
'SimpleFreeFieldHRIR'
>>> sofa.GlobalAttributes.get("DataType").value
'FIR'
property Variables: _Variables | None

Return the SOFA variable collection wrapper.

Variables contain the numeric and string arrays stored in the SOFA file, including HRTF/HRIR data arrays, source positions, sampling rates, and frequency vectors.

Returns:

Variable access wrapper, or None when no SOFA file is loaded.

Return type:

Optional[_Variables]

Examples

Read acoustic data, source positions, and sample-rate values from a loaded SOFA file:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> sofa.Variables.get("Data.IR").value.shape
(793, 2, 256)
>>> sofa.Variables.get("SourcePosition").value.shape
(793, 3)
>>> sofa.Variables.get("Data.SamplingRate").value
array([44100.])
property VariableAttributes: _VariableAttributes | None

Return the SOFA variable-attribute collection wrapper.

Variable attributes are exposed with Variable:Attribute keys, such as SourcePosition:Type or Data.SamplingRate:Units. These attributes describe coordinate systems, units, and semantic labels required by SOFA-based HRTF workflows.

Returns:

Variable-attribute access wrapper, or None when no SOFA file is loaded.

Return type:

Optional[_VariableAttributes]

Examples

Read coordinate-system and units metadata for source positions:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> sofa.VariableAttributes.get("SourcePosition:Type").value
'spherical'
>>> sofa.VariableAttributes.get("SourcePosition:Units").value
'degree, degree, metre'
create_dimension(name, value)

Create a fixed-size dimension in the loaded SOFA object.

Dimensions define the axes used by SOFA variables. For example, M commonly indexes measurements or source positions, R indexes receivers, N indexes time samples, and E indexes string lengths or emitters depending on the convention.

Parameters:
  • name (str) – Dimension name to create.

  • value (int) – Dimension size passed to netCDF4.Dataset.createDimension.

Raises:
  • ValueError – If no SOFA file is loaded or if the dimension already exists.

  • Exception – Propagates errors raised by netCDF4 when the netCDF4 storage handle is not writable or the dimension cannot be created.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Add a custom dimension to an in-memory clone and inspect the new dimension metadata:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_dimension("Q", 3)
>>> editable.Dimensions.get("Q").value
3
>>> editable.Dimensions.get("Q").is_unlimited
False
rename_dimension(old_name, new_name)

Rename an existing dimension in the loaded SOFA object.

The operation delegates to netCDF4 renameDimension and therefore updates the dimension name at the storage layer. Use this only when you also understand how existing SOFA variables depend on the dimension.

Parameters:
  • old_name (str) – Existing dimension name.

  • new_name (str) – New dimension name.

Raises:
  • ValueError – If no SOFA file is loaded or if old_name does not exist.

  • Exception – Propagates errors raised by netCDF4, including attempts to rename dimensions on read-only netCDF4 storage handles or to invalid names.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Rename a custom dimension on an in-memory clone before adding variables that depend on it:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_dimension("Q", 2)
>>> editable.rename_dimension("Q", "Q2")
>>> editable.Dimensions.get("Q2").value
2
create_global_attribute(name, value=None)

Create a global attribute on the loaded SOFA object.

Global attributes describe file-level SOFA metadata such as SOFAConventions, SOFAConventionsVersion, DataType, application metadata, and date fields. This method adds a new global attribute and refuses to overwrite an existing one.

Parameters:
  • name (str) – Global attribute name to create.

  • value (Optional[str], optional) – Attribute value. An empty string is stored when None is supplied.

Raises:
  • ValueError – If no SOFA file is loaded or if the global attribute already exists.

  • Exception – Propagates errors raised by netCDF4 when the attribute cannot be written.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Add file-level metadata to a clone without changing the source SOFA file:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_global_attribute(
...     "ExampleNote",
...     "created from a clone",
... )
>>> editable.GlobalAttributes.get("ExampleNote").value
'created from a clone'
modify_global_attribute(name, value)

Modify an existing global attribute on the loaded SOFA object.

This method updates file-level metadata that already exists on the netCDF4 storage handle. It is commonly used by HRTF save workflows to keep SOFAConventions, DataType, DateModified, and hrtfpykit API metadata synchronized after IR/TF changes.

Parameters:
  • name (str) – Existing global attribute name.

  • value (str) – New attribute value.

Raises:
  • ValueError – If no SOFA file is loaded or if the global attribute does not exist.

  • Exception – Propagates errors raised by netCDF4 when the attribute cannot be written.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Update a global attribute on a cloned SOFA object and read the edited value back through the global-attribute wrapper:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_global_attribute("ExampleNote", "initial note")
>>> editable.modify_global_attribute("ExampleNote", "updated note")
>>> editable.GlobalAttributes.get("ExampleNote").value
'updated note'
delete_global_attribute(name)

Delete a global attribute from the loaded SOFA object.

Removing global attributes can make a SOFA file invalid if required convention metadata is deleted. Use this method for controlled editing workflows where the resulting file will be validated or completed before saving.

Parameters:

name (str) – Attribute name to remove.

Raises:
  • ValueError – If no SOFA file is loaded or if the global attribute does not exist.

  • Exception – Propagates errors raised by netCDF4 when the attribute cannot be removed.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Remove a custom global attribute from an in-memory clone:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_global_attribute("ExampleNote", "temporary")
>>> editable.delete_global_attribute("ExampleNote")
>>> "ExampleNote" in editable.GlobalAttributes.get_names()
False
create_variable_attribute(name, value=None)

Create an attribute on an existing SOFA variable.

Variable attributes describe variable-specific metadata such as units, coordinate system type, and long names. The public key format is Variable:Attribute so the same style can be used by VariableAttributes and attributes.

Parameters:
  • name (str) – Attribute key in the form Variable:Attribute.

  • value (Optional[str], optional) – Attribute value. An empty string is stored when None is supplied.

Raises:
  • ValueError – If no SOFA file is loaded, name is malformed, the target variable does not exist, or the variable attribute already exists.

  • Exception – Propagates errors raised by netCDF4 when the attribute cannot be written.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Add metadata to the HRIR variable on a cloned SOFA object:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_variable_attribute(
...     "Data.IR:ExampleNote",
...     "time-domain data",
... )
>>> editable.VariableAttributes.get("Data.IR:ExampleNote").value
'time-domain data'
modify_variable_attribute(name, value)

Modify an existing attribute on a SOFA variable.

Use this method to update variable metadata without changing the variable data array. For HRTF files this is typically used for units and coordinate-system metadata, for example SourcePosition:Type or Data.SamplingRate:Units.

Parameters:
  • name (str) – Attribute key in the form Variable:Attribute.

  • value (str) – New attribute value.

Raises:
  • ValueError – If no SOFA file is loaded, name is malformed, the target variable does not exist, or the variable attribute does not exist.

  • Exception – Propagates errors raised by netCDF4 when the attribute cannot be written.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Update metadata on the HRIR variable of a cloned SOFA object:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_variable_attribute("Data.IR:ExampleNote", "initial")
>>> editable.modify_variable_attribute("Data.IR:ExampleNote", "edited copy")
>>> editable.VariableAttributes.get("Data.IR:ExampleNote").value
'edited copy'
delete_variable_attribute(name)

Delete an attribute from a SOFA variable.

Removing variable attributes can make a SOFA file ambiguous or invalid when the attribute is required by the declared convention. For example, source-position units and coordinate-system type are required by hrtfpykit source-grid logic.

Parameters:

name (str) – Attribute key in the form Variable:Attribute.

Raises:
  • ValueError – If no SOFA file is loaded, name is malformed, the target variable does not exist, or the variable attribute does not exist.

  • Exception – Propagates errors raised by netCDF4 when the attribute cannot be removed.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Delete a custom variable attribute after using it during an editing workflow:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_variable_attribute("Data.IR:ExampleNote", "temporary")
>>> editable.delete_variable_attribute("Data.IR:ExampleNote")
>>> "Data.IR:ExampleNote" in editable.VariableAttributes.get_names()
False
create_variable(name, data, dimensions, dtype=None, attributes=None)

Create a SOFA variable and optionally attach metadata.

The new variable is created with the provided dimension names and data. Data are converted to a NumPy array, checked against the target dimension shape, and assigned through netCDF4 broadcasting. This is used by HRTF update workflows when a converted representation requires variables that were not present in the original SOFA file, such as creating frequency-domain variables when saving as SimpleFreeFieldHRTF.

Parameters:
  • name (str) – Variable name to create, for example Data.IR, Data.Real, Data.Imag, or N.

  • data (Union[np.ndarray, list]) – Data assigned to the new variable. The value is converted with np.array before shape checks and assignment.

  • dimensions (Union[tuple[str, ...], list[str]]) – Existing netCDF4 dimension names in storage order.

  • dtype (Optional[Union[str, np.dtype]], optional) – Data type passed to netCDF4.Dataset.createVariable. If dtype is None, the converted data array dtype is used.

  • attributes (Optional[Dict[str, Any]], optional) – Optional variable attributes to set after variable creation.

Raises:
  • ValueError – If no SOFA file is loaded, the variable already exists, one or more dimensions are missing, or data cannot be broadcast to the requested shape.

  • Exception – Propagates errors raised by netCDF4 during variable creation, attribute assignment, or data assignment.

Return type:

None

Notes

The function warns when dimension sizes do not coincide with the netCDF4 dimensions and raises an error if the data cannot be broadcast to the target shape. Unlimited dimensions use the supplied data size on that axis when available.

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Create a small derived variable on a cloned SOFA object and attach units metadata to it:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_dimension("Q", 3)
>>> editable.create_variable(
...     "ExampleVector",
...     [1.0, 2.0, 3.0],
...     ("Q",),
...     attributes={"Units": "1"},
... )
>>> editable.Variables.get("ExampleVector").value
array([1., 2., 3.])
>>> editable.VariableAttributes.get("ExampleVector:Units").value
'1'
modify_variable(name, data)

Overwrite data for an existing SOFA variable.

The replacement data are converted to a NumPy array, validated against the variable’s dimension shape, and assigned through netCDF4. The variable definition, dimensions, dtype, and attributes are preserved; only its stored values are replaced.

Parameters:
  • name (str) – Existing variable name.

  • data (Union[np.ndarray, list]) – New variable data. The value is converted with np.array before shape checks and assignment.

Raises:
  • ValueError – If no SOFA file is loaded, the variable does not exist, or data cannot be broadcast to the variable shape.

  • Exception – Propagates errors raised by netCDF4 during data assignment.

Return type:

None

Notes

The function warns when dimension sizes do not coincide with the netCDF4 dimensions and raises an error if the data cannot be broadcast to the target shape. For unlimited dimensions, the replacement array’s axis length is accepted when provided.

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Replace HRIR samples on a cloned SOFA object while preserving the Data.IR variable definition and metadata:

>>> import numpy as np
>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> ir = editable.Variables.get("Data.IR").value
>>> edited_ir = np.array(ir, copy=True)
>>> edited_ir[..., :8] = 0.0
>>> editable.modify_variable("Data.IR", edited_ir)
>>> editable.Variables.get("Data.IR").value[0, 0, :8]
array([0., 0., 0., 0., 0., 0., 0., 0.])
delete_variable(name)

Delete a variable from the loaded SOFA object.

This method removes a variable by name from the underlying netCDF4 storage handle. Deleting convention-required variables can make a SOFA file invalid; validate or rebuild required content before saving the result.

Parameters:

name (str) – Variable name to remove.

Raises:
  • ValueError – If no SOFA file is loaded or if the variable does not exist.

  • Exception – Propagates errors raised by netCDF4 when the variable cannot be removed.

Return type:

None

Notes

Editing a SOFA file requires writable access. The recommended workflow is to load the original SOFA file, create an in-memory clone with clone(), apply edits to the clone, and save when you are ready. Direct in-place editing with mode r+ is still available for expert users.

Examples

Remove a custom variable from a cloned SOFA object after using it as temporary metadata:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_dimension("Q", 3)
>>> editable.create_variable("ExampleVector", [1.0, 2.0, 3.0], ("Q",))
>>> editable.delete_variable("ExampleVector")
>>> "ExampleVector" in editable.Variables.get_names()
False
save(path=None, overwrite=False)

Save the current SOFA object to disk.

The method writes the currently loaded SOFA object content to disk. When path is omitted, the object is synchronized back to its original file path recorded in path. When path is provided, a complete netCDF4 copy is written to a temporary file and then moved into place.

Parameters:
  • path (Optional[Union[str, pathlib.Path]], optional) – Target path. If path is None, the loaded SOFA object is synchronized to the original path recorded in path.

  • overwrite (bool, optional) – If True, allows replacing an existing destination file when path is provided.

Returns:

Path to the saved SOFA file.

Return type:

pathlib.Path

Raises:
  • ValueError – If no SOFA file is loaded or if path is omitted and the SOFA object has no original path.

  • FileExistsError – If the destination already exists and overwrite is False.

  • Exception – Propagates errors raised by netCDF4 or the filesystem while copying dimensions, attributes, variables, or replacing the target file.

Notes

Calling save() without a path synchronizes the loaded SOFA content back to the original file recorded in path.

Cloned SOFA objects and objects returned by copy_with() are independent in-memory SOFA objects. If one of those objects should replace an existing SOFA file on disk, save it to that filename with overwrite=True. In that case the method writes a temporary copy first and then replaces the destination file.

This method copies dimensions, global attributes, variables, variable attributes, and variable values. It does not run SOFA convention validation before writing; call the validation utilities explicitly when validation is part of the workflow.

Examples

Save an edited clone to a relative output path:

>>> from pathlib import Path
>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_global_attribute("ExampleNote", "saved copy")
>>> output_dir = Path("processed")
>>> output_dir.mkdir(exist_ok=True)
>>> saved_path = editable.save(
...     output_dir / "P0001_sofa_copy.sofa",
...     overwrite=True,
... )
>>> saved_path.name
'P0001_sofa_copy.sofa'
clone()

Create an in-memory writable clone of the current SOFA object.

The clone contains a full copy of dimensions, global attributes, variables, variable attributes, and variable values from the current SOFA object. It is backed by a diskless netCDF4 Dataset and has no file path until saved.

Returns:

New SOFA instance backed by an independent diskless netCDF4 storage handle.

Return type:

SOFA

Raises:
  • ValueError – If no SOFA file is loaded.

  • Exception – Propagates errors raised by netCDF4 while copying SOFA content.

Notes

The clone is an in-memory writable copy of the current SOFA object. Each call creates a new independent diskless netCDF4 storage handle, so cloning the same SOFA object multiple times is supported. Because the clone is independent from the original NetCDF handle, you can later save it to a new filename or replace an existing file with save() with overwrite enabled.

Examples

Clone a loaded SOFA object before editing metadata, leaving the source SOFA object unchanged:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> editable = sofa.clone()
>>> editable.create_global_attribute("ExampleNote", "clone only")
>>> editable.path is None
True
>>> editable.GlobalAttributes.get("ExampleNote").value
'clone only'
>>> "ExampleNote" in sofa.GlobalAttributes.get_names()
False
copy_with(dim_sizes=None, global_attributes=None, variable_attributes=None, variables=None)

Create a modified in-memory copy of the current SOFA object.

copy_with() is a structured cloning helper for workflows that need to resize fixed dimensions or replace existing arrays while preserving the rest of the SOFA file. It is used by HRTF save/update logic when transformed IR/TF data no longer match the original SOFA dimensions.

Parameters:
  • dim_sizes (dict[str, int] | None) – Size overrides for existing fixed dimensions. Unlimited dimensions cannot be overridden.

  • global_attributes (dict[str, Any] | None) – Global attributes to add or replace in the copied SOFA object.

  • variable_attributes (dict[str, dict[str, Any]] | None) – Per-variable attributes to add or replace. The outer keys are existing variable names and inner keys are attribute names without the Variable: prefix.

  • variables (dict[str, numpy.ndarray] | None) – Replacement data for existing variables. New variables cannot be created with this method.

Returns:

New SOFA instance backed by an independent diskless netCDF4 storage handle with the requested overrides applied.

Return type:

SOFA

Raises:
  • ValueError – If the SOFA file is not loaded, an override refers to a missing dimension or variable, or a provided array cannot be broadcast to the target variable shape.

  • Exception – Propagates errors raised by netCDF4 while copying or assigning SOFA content.

Notes

If you override a dimension size, provide replacement arrays for all variables that depend on that dimension unless their existing values can still broadcast to the new target shape. Use create_variable() on a writable copy when you need to add brand-new variables.

Examples

Create a resized copy with shorter HRIR data while keeping the original SOFA object unchanged:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> ir = sofa.Variables.get("Data.IR").value
>>> cropped = sofa.copy_with(
...     dim_sizes={"N": 128},
...     variables={"Data.IR": ir[..., :128]},
... )
>>> sofa.Variables.get("Data.IR").value.shape
(793, 2, 256)
>>> cropped.Variables.get("Data.IR").value.shape
(793, 2, 128)
summary()

Return a text summary of the loaded SOFA object.

The summary is intended for quick inspection in notebooks, terminals, and debugging logs. It lists global attributes first, then each variable with its dimension names, dimension sizes, and variable attributes.

Returns:

Multi-line summary of global attributes, variables, dimensions, and variable attributes.

Return type:

str

Raises:

ValueError – If no SOFA file is loaded.

Notes

This method does not validate the file and does not print by itself. It only builds and returns the summary string.

Examples

Build a text summary and check that it includes the main SOFA sections and HRIR variable dimensions:

>>> from hrtfpykit.sofa import load_sofa
>>> sofa = load_sofa("hrtfs/P0001_FreeFieldComp_44kHz.sofa")
>>> summary = sofa.summary()
>>> summary.splitlines()[:3]
['****************************', '     GLOBAL ATTRIBUTES', '****************************']
>>> "Data.IR : dimensions= (M=793, R=2, N=256)" in summary
True

Composed interfaces

SOFA keeps the loaded SOFA file around one netCDF4 storage handle and exposes the main SOFA file surfaces through composed interface properties. In normal use, users do not create those interface objects directly. They load or receive a SOFA instance and access each surface from that instance: sofa.Dimensions for dimension names, sizes, and wrapped dimension objects; sofa.GlobalAttributes for file-level convention and application metadata; sofa.Variables for SOFA arrays such as HRTF/HRIR data, source positions, sampling rates, and frequency vectors; and sofa.VariableAttributes for per-variable metadata such as coordinate-system types, units, and semantic labels.

All four access paths read the same parent SOFA state. When no SOFA file is loaded they return None; when a file is loaded, they reflect the current sofa.netCDF4_dataset handle used by inspection, editing, summary, clone, and save workflows.

class hrtfpykit.sofa.data._Dimensions(dataset=None)

Expose SOFA dimensions from a netCDF4-backed SOFA storage handle.

_Dimensions backs Dimensions. It exposes dimension names, sizes, wrapped dimension objects, and a compact text summary. Dimension wrappers are used to inspect SOFA axes such as M for measurements, R for receivers, and N for samples or frequency bins, depending on the active convention.

Parameters:

dataset (netCDF4.Dataset) – Open netCDF4 storage handle for a SOFA file.

Raises:

ValueError – If dataset is None.

get_names()

Return all dimension names in storage order.

Returns:

Names from dataset.dimensions on the netCDF4 storage handle.

Return type:

list[str]

get_values()

Return all dimension sizes in storage order.

Returns:

Dimension sizes matching the order returned by get_names(). Unlimited dimensions report their current netCDF4 size.

Return type:

list[int]

get(name)

Return one wrapped SOFA dimension by name.

Parameters:

name (str) – Dimension name to resolve.

Returns:

Wrapped dimension metadata containing the name, size, and unlimited flag.

Return type:

DimensionsWrap

Raises:

ValueError – If name is not present in the netCDF4 dimensions.

get_all()

Return all dimensions as wrapped objects.

Returns:

Mapping from dimension names to wrapped dimension metadata.

Return type:

dict[str, DimensionsWrap]

summary()

Return a formatted summary of SOFA dimensions.

Returns:

Multi-line text where each line has name = size. Dimensions are sorted alphabetically to keep the summary stable.

Return type:

str

__getitem__(name)

Return a wrapped dimension using indexing syntax.

Parameters:

name (str) – Dimension name.

Returns:

Wrapped dimension metadata.

Return type:

DimensionsWrap

Raises:

ValueError – If name is not present in the netCDF4 dimensions.

__iter__()

Iterate over wrapped dimensions.

Returns:

Iterator over all dimensions in storage order.

Return type:

Iterator[DimensionsWrap]

__len__()

Return the number of dimensions in the netCDF4 storage handle.

Returns:

Number of entries in dataset.dimensions on the netCDF4 storage handle.

Return type:

int

class hrtfpykit.sofa.data._GlobalAttributes(dataset=None)

Expose file-level SOFA metadata from a netCDF4 storage handle.

_GlobalAttributes backs GlobalAttributes. It exposes file-level metadata such as SOFAConventions, SOFAConventionsVersion, DataType, application metadata, and date fields through the shared attribute-wrapper API.

Parameters:

dataset (netCDF4.Dataset) – Open netCDF4 storage handle for a SOFA file.

Raises:

ValueError – If dataset is None.

summary()

Return a formatted summary of global SOFA attributes.

Returns:

Multi-line summary with a header followed by GLOBAL:name = value lines. Returns an empty string when the SOFA file has no global attributes.

Return type:

str

__getitem__(key)

Return a wrapped attribute using indexing syntax.

Parameters:

key (str) – Attribute key accepted by get().

Returns:

Wrapped attribute metadata.

Return type:

AttributesWrap

Raises:

ValueError – If key does not resolve to an available attribute.

__iter__()

Iterate over wrapped attributes.

Returns:

Iterator over all wrapped attributes in collection order.

Return type:

Iterator[AttributesWrap]

__len__()

Return the number of attributes in the collection.

Returns:

Number of attribute keys returned by get_names().

Return type:

int

get(name)

Return one wrapped attribute by name.

Parameters:

name (str) – Attribute key in the format expected by the concrete collection. Global attributes use the plain attribute name. Variable attributes use Variable:Attribute.

Returns:

Wrapped attribute metadata with the concrete collection’s attribute_type label.

Return type:

AttributesWrap

Raises:

ValueError – If name does not resolve to an available attribute in the wrapped collection.

get_all()

Return all attributes as wrapped objects.

Returns:

Mapping from attribute keys to wrapped attribute metadata.

Return type:

dict[str, AttributesWrap]

get_names()

Return all attribute names in collection order.

Returns:

Attribute keys produced by _iter_items().

Return type:

list[str]

get_values()

Return all raw attribute values in collection order.

Returns:

Attribute values produced by _iter_items().

Return type:

list[Any]

class hrtfpykit.sofa.data._Variables(dataset=None)

Expose SOFA variable data and metadata from a netCDF4 storage handle.

_Variables backs Variables. It exposes variable names, NumPy values, wrapped variable objects, and a summary of variable dimensions and attributes. This collection is the primary read path for SOFA arrays such as Data.IR, Data.Real, Data.Imag, SourcePosition, Data.SamplingRate, and N.

Parameters:

dataset (netCDF4.Dataset) – Open netCDF4 storage handle for a SOFA file.

Raises:

ValueError – If dataset is None.

get_names()

Return all variable names in storage order.

Returns:

Names from dataset.variables on the netCDF4 storage handle.

Return type:

list[str]

get_values()

Return all variable values as NumPy arrays.

Returns:

Complete variable data arrays in storage order. Each variable is read with full slicing and converted with numpy.array().

Return type:

list[np.ndarray]

Raises:

Exception – Propagates errors raised by netCDF4 when a variable cannot be read.

get(name)

Return one wrapped SOFA variable by name.

Parameters:

name (str) – Variable name to resolve.

Returns:

Wrapped variable exposing NumPy data through value and variable attributes through attributes.

Return type:

VariablesWrap

Raises:

ValueError – If name is not present in the netCDF4 variables.

get_all()

Return all variables as wrapped objects.

Returns:

Mapping from variable names to wrapped variable objects.

Return type:

dict[str, VariablesWrap]

summary()

Return a formatted summary of SOFA variables.

Returns:

Multi-line summary listing each variable, its dimension names and current dimension sizes, followed by any variable attributes. Missing dimension references are displayed with ?.

Return type:

str

__getitem__(key)

Return a wrapped variable using indexing syntax.

Parameters:

key (str) – Variable name.

Returns:

Wrapped variable object.

Return type:

VariablesWrap

Raises:

ValueError – If key is not present in the netCDF4 variables.

__iter__()

Iterate over wrapped SOFA variables.

Returns:

Iterator over all variables in storage order.

Return type:

Iterator[VariablesWrap]

__len__()

Return the number of variables in the netCDF4 storage handle.

Returns:

Number of entries in dataset.variables on the netCDF4 storage handle.

Return type:

int

class hrtfpykit.sofa.data._VariableAttributes(dataset=None)

Expose attributes attached to individual SOFA variables.

_VariableAttributes backs VariableAttributes. It exposes attributes attached to individual variables using the hrtfpykit key format Variable:Attribute. These attributes describe units, coordinate systems, and semantic labels required by SOFA-based HRTF workflows.

Parameters:

dataset (netCDF4.Dataset) – Open netCDF4 storage handle for a SOFA file.

Raises:

ValueError – If dataset is None.

summary()

Return a formatted summary of SOFA variable attributes.

Returns:

Multi-line summary with a header followed by Variable:Attribute = value lines. Returns an empty string when no variable attributes are present.

Return type:

str

__getitem__(key)

Return a wrapped attribute using indexing syntax.

Parameters:

key (str) – Attribute key accepted by get().

Returns:

Wrapped attribute metadata.

Return type:

AttributesWrap

Raises:

ValueError – If key does not resolve to an available attribute.

__iter__()

Iterate over wrapped attributes.

Returns:

Iterator over all wrapped attributes in collection order.

Return type:

Iterator[AttributesWrap]

__len__()

Return the number of attributes in the collection.

Returns:

Number of attribute keys returned by get_names().

Return type:

int

get(name)

Return one wrapped attribute by name.

Parameters:

name (str) – Attribute key in the format expected by the concrete collection. Global attributes use the plain attribute name. Variable attributes use Variable:Attribute.

Returns:

Wrapped attribute metadata with the concrete collection’s attribute_type label.

Return type:

AttributesWrap

Raises:

ValueError – If name does not resolve to an available attribute in the wrapped collection.

get_all()

Return all attributes as wrapped objects.

Returns:

Mapping from attribute keys to wrapped attribute metadata.

Return type:

dict[str, AttributesWrap]

get_names()

Return all attribute names in collection order.

Returns:

Attribute keys produced by _iter_items().

Return type:

list[str]

get_values()

Return all raw attribute values in collection order.

Returns:

Attribute values produced by _iter_items().

Return type:

list[Any]