pycsamt.ai.losses.response#

Electromagnetic response-consistency losses.

These losses implement the L_response term of the staged inversion objective in the AI-inversion plan:

L = w_m * L_model + lambda_x * L_grad_x + lambda_z * L_grad_z
    + lambda_tv * L_TV + lambda_d * L_response

Inputs are predicted and observed complex impedance arrays sharing the canonical shape (station, frequency, component) used by ForwardResult and SurveyData. When positive standard errors are supplied, residuals are normalized by them before the elementwise penalty is applied, matching the usual normalized-RMS EM data-misfit convention.

All functions operate on plain NumPy arrays so the module stays importable without an optional deep-learning backend.

Functions

response_loss_from_contracts(forward, ...[, ...])

Compute L_response directly from canonical result/survey.

response_residual_loss(predicted, observed, *)

Compare predicted and observed complex impedance responses.

Classes

ResponseLoss([kind, reduction])

Configurable, callable response-consistency loss.

ResponseLossResult(value, kind, reduction, ...)

Immutable scalar result of a response-consistency loss.

class pycsamt.ai.losses.response.ResponseLossResult(value, kind, reduction, n_valid, weight_sum, normalized)[source]

Bases: object

Immutable scalar result of a response-consistency loss.

Parameters:
  • value (float) – Reduced loss value. nan when no cell was included and reduction="mean".

  • kind ({"l1", "l2"}) – Elementwise penalty applied to each residual magnitude.

  • reduction ({"mean", "sum"}) – Reduction applied over valid cells.

  • n_valid (int) – Number of impedance cells included after masking.

  • weight_sum (float) – Number of included cells; kept for interface parity with other loss results in this package.

  • normalized (bool) – Whether residuals were divided by a positive standard error before the penalty was applied.

Examples

>>> import numpy as np
>>> pred = np.array([1 + 1j, 2 + 2j])
>>> obs = np.array([1 + 1j, 0 + 0j])
>>> response_residual_loss(pred, obs).value
4.0
value: float
kind: str
reduction: str
n_valid: int
weight_sum: float
normalized: bool
class pycsamt.ai.losses.response.ResponseLoss(kind='l2', reduction='mean')[source]

Bases: object

Configurable, callable response-consistency loss.

Parameters:
  • kind ({"l1", "l2"}, default="l2") – Elementwise penalty applied to each residual magnitude.

  • reduction ({"mean", "sum"}, default="mean") – Reduction applied over included cells.

Examples

>>> import numpy as np
>>> loss = ResponseLoss()
>>> pred = np.array([1 + 1j, 2 + 2j])
>>> obs = np.array([1 + 1j, 0 + 0j])
>>> loss(pred, obs).value
4.0
kind: str = 'l2'
reduction: str = 'mean'
pycsamt.ai.losses.response.response_residual_loss(predicted, observed, *, errors=None, valid=None, kind='l2', reduction='mean')[source]

Compare predicted and observed complex impedance responses.

Parameters:
  • predicted (array-like of complex) – Forward-simulated impedance. Any shape is accepted; the canonical layout is (station, frequency, component).

  • observed (array-like of complex) – Observed impedance with the same shape.

  • errors (array-like or None, optional) – Positive absolute standard errors, same shape as predicted. When given, each residual is divided by its error before the elementwise penalty, matching the normalized-RMS EM data-misfit convention. Entries with a non-finite or non-positive error are excluded rather than raising.

  • valid (array-like of bool or None, optional) – Explicit observation mask, combined with finite-value masking of predicted, observed, and errors.

  • kind ({"l1", "l2"}, default="l2") – Elementwise penalty applied to each residual magnitude.

  • reduction ({"mean", "sum"}, default="mean") – Reduction applied over included cells.

Returns:

Reduced response-consistency penalty, L_response.

Return type:

ResponseLossResult

Examples

>>> import numpy as np
>>> pred = np.array([1 + 1j, 2 + 2j])
>>> obs = np.array([1 + 1j, 0 + 0j])
>>> response_residual_loss(pred, obs, kind="l2").value
4.0
>>> response_residual_loss(
...     pred, obs, errors=np.array([1.0, 2.0]), kind="l2"
... ).value
1.0
pycsamt.ai.losses.response.response_loss_from_contracts(forward, observed, *, kind='l2', reduction='mean', use_errors=True)[source]

Compute L_response directly from canonical result/survey.

Requires exact station, component, and frequency alignment between forward and observed rather than silently interpolating or reordering either axis, per the survey-matching principle in the AI-inversion plan.

Parameters:
  • forward (ForwardResult) – Predicted impedance from a Maxwell backend adapter.

  • observed (SurveyData) – Observed survey impedance to compare against.

  • kind ({"l1", "l2"}, default="l2") – Elementwise penalty applied to each residual magnitude.

  • reduction ({"mean", "sum"}, default="mean") – Reduction applied over included cells.

  • use_errors (bool, default=True) – Normalize residuals by observed.impedance_error when it is available.

Returns:

Reduced response-consistency penalty, L_response.

Return type:

ResponseLossResult

Raises:
  • TypeError – If forward or observed has the wrong type.

  • ValueError – If station names, components, or frequencies are not identical and identically ordered on both inputs.

Examples

>>> import numpy as np
>>> from pycsamt.ai.data import SurveyData
>>> from pycsamt.forward.maxwell import ForwardResult, SolverDiagnostics
>>> z = np.array([[[1 + 1j]]])
>>> observed = SurveyData(z, [10.0], ["S1"], ["zxy"], [[0, 0]])
>>> diagnostics = SolverDiagnostics([[True]], [[1]], [[0.0]], 0.01)
>>> forward = ForwardResult(
...     "a" * 64,
...     [10.0],
...     ["S1"],
...     ["zxy"],
...     z,
...     None,
...     "demo",
...     "1",
...     diagnostics,
... )
>>> response_loss_from_contracts(forward, observed).value
0.0