Utility Functions (anglepy.utils)

anglepy.utils.circular_conditional_equality_test(X_1, y_1, X_2, y_2, angle_params, random_state=42)

Tests the equality of conditional distributions for circular responses using the ANGLE framework.

This function evaluates the null hypothesis \(H_0: P_{Y|X}^{(1)} = P_{Y|X}^{(2)}\) against the alternative \(H_1: P_{Y|X}^{(1)} \neq P_{Y|X}^{(2)}\). It trains the ANGLE generative model once on the first dataset and evaluates the generative mismatch on a randomly partitioned second dataset using two-sample circular tests.

Parameters:
  • X_1 (array-like or torch.Tensor) – Covariates for the first sample, representing \(\mathcal{S}_1\).

  • y_1 (array-like or torch.Tensor) – Angular responses for the first sample \(\mathcal{S}_1\), bounded in \([0, 2\pi)\).

  • X_2 (array-like or torch.Tensor) – Covariates for the second sample, representing \(\mathcal{S}_2\).

  • y_2 (array-like or torch.Tensor) – Angular responses for the second sample \(\mathcal{S}_2\), bounded in \([0, 2\pi)\).

  • angle_params (dict) – Dictionary of hyperparameters used to initialize the ANGLE model.

  • random_state (int, default=42) – Random seed for reproducibility in model initialization and dataset partitioning.

Returns:

  • p_val_kuiper (float) – The \(p\)-value obtained from the two-sample Kuiper’s test.

  • p_val_manova (float) – The \(p\)-value obtained from the Trigonometric MANOVA two-sample test.

Notes

The testing procedure implements Algorithm 1 from the ANGLE framework:

  1. Fit the ANGLE network on \(\mathcal{S}_1\) to obtain the generative model \(\tilde{g}_1\).

  2. Randomly partition \(\mathcal{S}_2\) into two equal halves, \(\mathcal{S}_{21}\) and \(\mathcal{S}_{22}\).

  3. Generate synthetic circular responses \(\tilde{Y}_{21,i} = \tilde{g}_1(X_{21,i}, \epsilon_i)\) for the covariates in \(\mathcal{S}_{21}\).

  4. Compare the synthetic responses \(\tilde{\mathcal{S}}_{21}\) with the true held-out responses \(\mathcal{S}_{22}\) using standard circular two-sample tests. Under \(H_0\), these sets of responses are approximately identically distributed.

anglepy.utils.get_circular_medians(ensemble)

Calculates the circular median along the last dimension of the ensemble.

Parameters:

ensemble (torch.Tensor) – A tensor of shape \((..., \text{sample\_size})\). Predictions for a circular target in the range \([0, 2\pi)\).

Returns:

A tensor of shape \((...)\) containing the computed point medians.

Return type:

torch.Tensor

anglepy.utils.get_circular_quantiles(ensemble, a)

Calculates the circular conditional quantile along the last dimension.

Parameters:
  • ensemble (torch.Tensor) – A tensor of shape \((..., \text{sample\_size})\). Predictions for a circular target in the range \([0, 2\pi)\).

  • a (float) – The quantile level in \((0, 1)\).

Returns:

A tensor of shape \((...)\) containing the computed point quantiles.

Return type:

torch.Tensor

anglepy.utils.plot_donut(y_test, y_pred, ax, title='Donut Plot')

Plots a donut plot on a given matplotlib Axes object. Considers North as 0 radians and angle increases clockwise. Reference: Jha, J., & Biswas, A. (2017). Multiple circular–circular regression. Statistical Modelling, 17(3), 142-171.

anglepy.utils.plot_spokeplot(y_test, y_pred, ax, r_inner=1, r_outer=2, title='Spokeplot')

Plots a spokeplot on a given matplotlib Axes object. Considers North as 0 radians and angle increases clockwise.