Simulators for Circular Data (anglepy.circular_simulators)

anglepy.circular_simulators.generate_atan2_circular_data(n_samples, beta1, beta2, n_circular_cov=0, noise_type='normal', noise_scale=0.5, random_seed=None, pi_range=False, a=4)

Generates circular data using a deterministic Arctan2 mapping of non-linearly interacting signals.

This function constructs circular responses by simulating raw linear and circular covariates, applying pre-additive noise, and embedding the circular features via sine and cosine transformations. Base linear signals (\(z_1, z_2\)) are computed and then heavily distorted using a cross-term \(\tanh\) function controlled by parameter a:

\[\mu_1 = z_1 + a \tanh(z_2)\]
\[\mu_2 = z_2 + a \tanh(z_1)\]

The final angular response is computed using the four-quadrant inverse tangent mapping, \(\theta = \arctan2(\mu_2, \mu_1)\), projecting the distorted Cartesian coordinates onto the unit circle.

Parameters:
  • n_samples (int) – The number of data points to generate.

  • beta1 (array_like) – The coefficient weights for the first base linear signal (\(z_1\)), which acts as the denominator/x-component prior to mapping.

  • beta2 (array_like) – The coefficient weights for the second base linear signal (\(z_2\)), which acts as the numerator/y-component prior to mapping. Must be the exact same length as beta1.

  • n_circular_cov (int, optional) – The number of circular covariates to generate (sampled from a von Mises distribution). Remaining covariate slots defined by the length of the beta arrays will be filled with standard normal linear covariates. Default is 0.

  • noise_type ({'normal', 'uniform'}, optional) – The statistical distribution of the pre-additive noise applied to the raw covariates before embedding. Default is ‘normal’.

  • noise_scale (float, optional) – The magnitude of the applied noise. If noise_type is ‘normal’, this acts as the standard deviation. If ‘uniform’, this acts as the symmetric boundary \([-\text{scale}, \text{scale}]\). Default is 0.5.

  • random_seed (int, optional) – Seed for the random number generator to ensure reproducibility. Default is None.

  • pi_range (bool, optional) – Determines the range of the output angles. If True, returns angles in the range \([-\pi, \pi]\). If False, returns angles in \([0, 2\pi)\). Default is False.

  • a (float, optional) – Multiplier controlling the strength of the non-linear cross-term interaction between the base signals. Setting a=0 results in a model driven purely by linear combinations of the covariates (approach 1). Default is 4.

Returns:

  • theta (ndarray) – 1D array of shape (n_samples,) containing the generated circular response variables (angles).

  • X_original (ndarray) – 2D array of shape (n_samples, n_linear_cov + n_circular_cov) containing the raw, un-noised covariates. Linear covariates are positioned in the first columns, followed by the raw circular covariates.

Raises:
  • ValueError – If beta1 and beta2 are not of the same length.

  • ValueError – If the beta arrays are too short to support the requested number of circular covariates (each circular covariate requires 2 beta weights for its sine/cosine embedding).

  • ValueError – If an unsupported noise_type is provided.

anglepy.circular_simulators.generate_pn_circular_data(n_samples, beta1, beta2, n_circular_cov=0, noise_type='uniform', noise_scale=0.05, random_seed=None, pi_range=False, a=2)

Generates circular data from a Projected Normal (PN) model using Approach 3 and 4, featuring pre-additive noise and non-linear covariate interactions.

This function simulates circular data by first generating latent bivariate normal vectors \((Y_1, Y_2)\) and projecting them onto the unit circle using the four-quadrant inverse tangent, \(\theta = \arctan2(Y_2, Y_1)\).

The latent means \((\mu_1, \mu_2)\) are calculated by applying pre-additive noise to the raw covariates, embedding any circular covariates into \(\cos\) and \(\sin\) components, computing base linear projections \((z_1, z_2)\), and finally applying a stable non-linear cross-term transformation controlled by the parameter a.

Parameters:
  • n_samples (int) – The number of data points to generate.

  • beta1 (array_like) – The coefficient weights for the first latent dimension projection (\(z_1\)).

  • beta2 (array_like) – The coefficient weights for the second latent dimension projection (\(z_2\)). Must be the exact same length as beta1.

  • n_circular_cov (int, optional) – The number of circular covariates to generate (sampled from a von Mises distribution). Remaining covariate slots defined by the length of the beta arrays will be filled with standard normal linear covariates. Default is 0.

  • noise_type ({'uniform', 'normal'}, optional) – The statistical distribution of the pre-additive noise applied to the raw covariates. Default is ‘uniform’.

  • noise_scale (float, optional) – The magnitude of the applied noise. If noise_type is ‘normal’, this acts as the standard deviation. If ‘uniform’, this acts as the symmetric boundary \([-\text{scale}, \text{scale}]\). Default is 0.05.

  • random_seed (int, optional) – Seed for the random number generator to ensure reproducibility. Default is None.

  • pi_range (bool, optional) – Determines the range of the output angles. If True, returns angles in the range \([-\pi, \pi]\). If False, returns angles in \([0, 2\pi)\). Default is False.

  • a (float, optional) – Multiplier controlling the strength of the non-linear cross-term interaction between the latent variables (e.g., \(\mu_1 = z_1 + a \tanh(z_2)\)). Setting a=0 results in a strictly linear model (approach 3). Default is 2.

Returns:

  • theta (ndarray) – 1D array of shape (n_samples,) containing the generated circular response variables (angles).

  • X_original (ndarray) – 2D array of shape (n_samples, n_linear_cov + n_circular_cov) containing the un-noised, raw covariates. Linear covariates are positioned in the first columns, followed by the raw circular covariates.

Raises:
  • ValueError – If beta1 and beta2 are not of the same length.

  • ValueError – If the beta arrays are too short to support the requested number of circular covariates (each circular covariate requires 2 beta weights for its sine/cosine embedding).

  • ValueError – If an unsupported noise_type is provided.

anglepy.circular_simulators.preanm_simulator(true_function='softplus', n_train=5000, n_eval=1000, x_lower=0, x_upper=2, x_eval_lower=-2, x_eval_upper=6, noise_std=1.0, noise_dist='gaussian', device=device(type='cpu'))

Simulates circular data from a Pre-Additive Noise Model (Pre-ANM) and computes the theoretical true conditional circular mean for an evaluation grid.

This simulator generates a training dataset where a base latent function \(f\) is applied to a noisy input \(X_n = X + \epsilon\), and the output is wrapped onto the unit circle:

\[Y = \arctan2(\sin(f(X + \epsilon)), \cos(f(X + \epsilon))) \pmod{2\pi}\]

Alongside the scatter training data, it calculates the true conditional circular mean \(\mathbb{E}[Y|X=x]\) over a linearly spaced extrapolation grid. Because the noise is pre-additive, the expected value requires marginalizing over the noise distribution. This is achieved via a high-sample Monte Carlo approximation at each grid point.

Code is inspired by Shen & Meinshausen (2025).

Parameters:
  • true_function (str or callable, optional) – The underlying base function \(f(x)\) to apply to the noisy covariates. If a string, accepted values are: * ‘softplus’: Applies nn.Softplus(). * ‘cubic’: Applies \(x^3 / 3\). * ‘square’: Applies \(\text{ReLU}(x)^2 / 2\). * ‘log’: Applies a piecewise function: a linear combination for \(x \le 2\) and \(\ln(1+x)\) for \(x > 2\). If a callable, it should accept and return a PyTorch tensor. Default is ‘softplus’.

  • n_train (int, optional) – The number of training samples to generate. The base covariates \(X\) are sampled uniformly. Default is 5000.

  • n_eval (int, optional) – The number of linearly spaced points to generate for the evaluation grid. Default is 1000.

  • x_lower (float, optional) – The lower bound of the uniform sampling distribution for the training covariates \(X\). Default is 0.

  • x_upper (float, optional) – The upper bound of the uniform sampling distribution for the training covariates \(X\). Default is 2.

  • x_eval_lower (float, optional) – The lower bound of the evaluation/extrapolation grid. Default is -2.

  • x_eval_upper (float, optional) – The upper bound of the evaluation/extrapolation grid. Default is 6.

  • noise_std (float, optional) – The standard deviation \(\sigma\) of the pre-additive noise \(\epsilon\). Default is 1.0.

  • noise_dist ({'gaussian', 'uniform'}, optional) – The statistical distribution of the pre-additive noise. If ‘uniform’, it is scaled internally to match the standard deviation specified by noise_std. Default is ‘gaussian’.

  • device (str or torch.device, optional) – The PyTorch device (e.g., ‘cpu’, ‘cuda’) on which the returned tensors should be allocated. Default is ‘cpu’.

Returns:

  • x_train (torch.Tensor) – A 2D tensor of shape (n_train, 1) containing the clean, uniformly sampled training covariates \(X\).

  • y_train (torch.Tensor) – A 2D tensor of shape (n_train, 1) containing the generated circular response variables \(Y\) in the range \([0, 2\pi)\).

  • x_eval (torch.Tensor) – A 2D tensor of shape (n_eval, 1) containing the linearly spaced evaluation/extrapolation grid.

  • y_eval_mean_circ (torch.Tensor) – A 2D tensor of shape (n_eval, 1) containing the Monte Carlo approximation of the true conditional circular mean at each point in x_eval. Values are in the range \([0, 2\pi)\).