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)\).