fips.Covariance.block_diag#

classmethod Covariance.block_diag(*covariances, name=None, **blocks)[source]#

Put independent covariances side by side: each on its own blocks, zero between.

Each part keeps its form (a Kronecker block stays factors, a diagonal one its variances), so the result costs what its parts do.

Parameters:
  • *covariances (Covariance) – Covariances that know their blocks, in order.

  • name (str | None) – The covariance’s name. So a block called "name" cannot be given by keyword: build its part on the block and give the Covariance in order.

  • **blocks (Covariance | _Model) – Parts named by block, after the positional ones: a covariance on that one block, or a CovarianceModel (as model.with_std(std)), which gets the block’s labels when built.

Returns:

The covariance on the blocks of every part, one after the other; while a part is a model, a CovarianceModel to build() on a space.

Return type:

Self | _Model

Raises:
  • TypeError – If name is a covariance or a model: a part for a block called "name", which the keyword cannot take.

  • ValueError – If no part is given, two have a block of one name, or a covariance given as block= is on another block.

Examples

>>> import pandas as pd
>>> from fips import Covariance, Independent, Space
>>> cells = Space({"flux": pd.Index(["a", "b"], name="cell")})
>>> sites = Space({"bias": pd.Index(["A"], name="site")})
>>> flux = Covariance.diagonal(4.0, cells)
>>> bias = Covariance.diagonal(1.0, sites)
>>> S = Covariance.block_diag(flux, bias)
>>> S.space
Space(flux: 2 x ['cell'], bias: 1 x ['site'])
>>> S.variances.values
array([4., 4., 1.])
>>> model = Covariance.block_diag(flux, bias=Independent().with_std(2.0))
>>> model.build(S.space).variances.values
array([4., 4., 4.])