socca.models.disk

Disk model component.

class socca.models.disk.Disk(radial=<socca.models.radial.sersic.Sersic object>, vertical=<socca.models.disk.vertical.HyperSecantHeight object>, **kwargs)[source]

Bases: Component

3D disk model combining radial and vertical profiles with inclination.

Creates a realistic disk galaxy model by combining a radial surface brightness profile with a vertical density distribution. The model accounts for disk inclination via line-of-sight integration.

Parameters:
  • radial (Profile, optional) – Radial profile defining in-plane surface brightness distribution. Default is Sersic(). Can be any 2D profile (Beta, Exponential, etc.).

  • vertical (Height, optional) – Vertical profile defining scale height and vertical structure. Default is HyperSecantHeight(). Can be HyperSecantHeight or ExponentialHeight.

  • **kwargs (dict) – Additional keyword arguments passed to Component.

Variables:
  • radial (Profile) – Radial profile component.

  • vertical (Height) – Vertical profile component.

  • profile (callable) – Combined 3D density profile rho(r, z) = radial(r) * vertical(z).

Notes

The 3D disk model: 1. Defines density as rho(r,z) = radial_profile(r) * vertical_profile(z) 2. Integrates along the line of sight to obtain projected surface brightness 3. Accounts for inclination by rotating the disk before integration 4. Uses numerical integration (trapezoidal rule) along z-direction

The inclination angle is stored in vertical.inc:

  • inc = 0: face-on (looking down on the disk)

  • inc = pi/2: edge-on (viewing disk from the side)

Line-of-sight integration parameters (vertical.losdepth, vertical.losbins) control accuracy and computation time. Larger losdepth and more losbins improve accuracy for highly inclined disks.

Examples

>>> from socca.models import Disk, Exponential
>>> from socca.models.disk.vertical import ExponentialHeight
>>> # Create edge-on exponential disk
>>> radial = Exponential(xc=180.5, yc=45.2, rs=0.02, Is=100)
>>> vertical = ExponentialHeight(zs=0.002, inc=np.pi/2)
>>> disk = Disk(radial=radial, vertical=vertical)
__init__(radial=<socca.models.radial.sersic.Sersic object>, vertical=<socca.models.disk.vertical.HyperSecantHeight object>, **kwargs)[source]

Initialize a 3D disk model from radial and vertical profiles.

Parameters:
  • radial (Profile, optional) – Radial profile component. Default is Sersic().

  • vertical (Height, optional) – Vertical profile component. Default is HyperSecantHeight().

  • **kwargs (dict) – Additional keyword arguments.

Notes

The component ID is synchronized between the Disk, radial, and vertical components to ensure consistent parameter naming in composite models.

getmap(img, convolve=False)[source]

Generate disk image via 3D line-of-sight integration.

Computes the projected surface brightness by integrating the 3D density distribution along the line of sight, accounting for inclination.

Parameters:
  • img (Image) – Image object containing grid, PSF, and WCS information.

  • convolve (bool, optional) – If True, convolve the model with the PSF. Default is False.

Returns:

Projected disk image on the image grid.

Return type:

ndarray

Raises:

ValueError – If any parameter is a prior distribution or set to None.

Warns:

UserWarning – If convolve=True but no PSF is defined.

Notes

The algorithm: 1. Creates 3D coordinate grids (r, z) accounting for inclination 2. Evaluates 3D density rho(r, z) = radial(r) * vertical(z) 3. Integrates along line of sight using trapezoidal rule 4. Averages over sub-pixel sampling 5. Optionally convolves with PSF

Integration accuracy controlled by:

  • vertical.losdepth: extent of integration

  • vertical.losbins: number of integration points

For edge-on disks, use larger losdepth (≥ 5*zs) and more losbins (≥ 200).

Examples

>>> from socca.models import Disk, Exponential
>>> from socca.models.disk.vertical import ExponentialHeight
>>> import numpy as np
>>> from socca.data import Image
>>> radial = Exponential(xc=180.5, yc=45.2, rs=0.02, Is=100)
>>> vertical = ExponentialHeight(zs=0.002, inc=np.pi/4)  # 45 deg
>>> disk = Disk(radial=radial, vertical=vertical)
>>> img = Image('observation.fits')
>>> disk_map = disk.getmap(img, convolve=True)
static getgrid(grid, xc, yc, losdepth, losbins=200, theta=0.0, inc=0.0)[source]

Compute 3D disk coordinates with rotation and inclination.

Generates 3D coordinate grids (r, z) for disk model evaluation, accounting for position angle and inclination transformations needed for line-of-sight integration through an inclined disk.

Parameters:
  • grid (Grid) – Grid object with .x and .y celestial coordinate arrays (deg).

  • xc (float) – Right ascension of disk center (deg).

  • yc (float) – Declination of disk center (deg).

  • losdepth (float) – Half-extent of line-of-sight integration (deg).

  • losbins (int, optional) – Number of integration points along line of sight. Default is 200.

  • theta (float, optional) – Position angle of disk major axis, east from north (rad). Default is 0.

  • inc (float, optional) – Inclination angle (0 = face-on, pi/2 = edge-on) (rad). Default is 0.

Returns:

  • rcube (ndarray) – 4D array of radial distances from disk center (deg). Shape: (ssize, losbins, ysize, xsize).

  • zcube (ndarray) – 4D array of heights above/below disk midplane (deg). Shape: (ssize, losbins, ysize, xsize).

Notes

The transformation sequence: 1. Center coordinates on (xc, yc) 2. Apply spherical geometry correction (cos(dec)) 3. Rotate by position angle theta 4. Create line-of-sight grid from -losdepth to +losdepth 5. Apply inclination rotation 6. Compute cylindrical radius r and height z

The inclination is measured from face-on:

  • inc = 0: face-on, z-axis points toward observer

  • inc = pi/2: edge-on, disk in plane of sky

The 4D arrays allow vectorized evaluation of the 3D density function across the entire image with sub-pixel sampling and line-of-sight integration.

This function is JIT-compiled with static losbins for performance.

parameters()[source]

Print formatted table of disk parameters from radial and vertical components.

Displays parameters from both the radial and vertical profile components, organized as ‘radial.parameter’ and ‘vertical.parameter’. Separates regular parameters from hyperparameters (integration settings).

Notes

Output format:

Model parameters

radial.xc [deg] : value | Right ascension of centroid radial.yc [deg] : value | Declination of centroid radial.rs [deg] : value | Scale radius vertical.zs [deg] : value | Scale height vertical.inc [rad] : value | Inclination angle (0=face-on)

Hyperparameters

vertical.losdepth [deg] : value | Half line-of-sight extent vertical.losbins [] : value | Number of integration points

Hyperparameters control the numerical integration accuracy but are not fitted parameters.

Examples

>>> from socca.models import Disk, Exponential
>>> from socca.models.disk.vertical import ExponentialHeight
>>> import numpy as np
>>> radial = Exponential(xc=180.5, yc=45.2, rs=0.02, Is=100)
>>> vertical = ExponentialHeight(zs=0.002, inc=np.pi/4)
>>> disk = Disk(radial=radial, vertical=vertical)
>>> disk.parameters()
Model parameters
================
radial.xc         [deg]    : 1.8050E+02 | Right ascension of centroid
radial.yc         [deg]    : 4.5200E+01 | Declination of centroid
...
parlist()[source]

Return list of parameter names from radial and vertical components.

Collects all parameters from both the radial and vertical profile components, with names prefixed as ‘radial.’ and ‘vertical.’.

Returns:

Combined list of parameter names from radial and vertical components. Names are prefixed with component type (e.g., ‘radial.xc’, ‘vertical.zs’).

Return type:

list of str

Notes

This method is used internally by Model.addcomponent() when adding a Disk component to a composite model, ensuring all parameters from both sub-components are registered.

Examples

>>> from socca.models import Disk, Exponential
>>> from socca.models.disk.vertical import ExponentialHeight
>>> radial = Exponential(xc=180.5, yc=45.2, rs=0.02, Is=100)
>>> vertical = ExponentialHeight(zs=0.002, inc=0.5)
>>> disk = Disk(radial=radial, vertical=vertical)
>>> disk.parlist()
['radial.xc', 'radial.yc', 'radial.theta', 'radial.e', 'radial.cbox',
 'radial.rs', 'radial.Is', 'vertical.losdepth', 'vertical.losbins',
 'vertical.inc', 'vertical.zs']

socca.models.disk.vertical

Vertical profiles for 3D disk galaxies.

class socca.models.disk.vertical.Height(**kwargs)[source]

Bases: Component

Base class for vertical density profiles in 3D disk models.

Defines the vertical (z-direction) structure of a disk galaxy. Used in combination with radial profiles to create 3D disk models via the Disk class.

Parameters:

**kwargs (dict) –

Keyword arguments including:

incfloat, optional

Inclination angle in radians (0 = face-on, pi/2 = edge-on).

losdepthfloat, optional

Half-extent of line-of-sight integration in degrees.

losbinsint, optional

Number of integration points along the line of sight.

positivebool, optional

Whether to enforce positivity constraint.

Variables:
  • inc (float) – Inclination angle (rad).

  • losdepth (float) – Half line-of-sight depth for numerical integration (deg).

  • losbins (int) – Number of points for line-of-sight integration (hyperparameter).

Notes

  • Subclasses must implement the abstract profile(z) method

  • The profile should return the density as a function of height z

  • losdepth and losbins control the numerical integration accuracy

  • Larger losdepth needed for extended vertical distributions

  • More losbins increase accuracy but decrease speed

__init__(**kwargs)[source]

Initialize a vertical profile component.

Parameters:

**kwargs (dict) – Keyword arguments including inc, losdepth, losbins, positive.

abstractmethod profile()[source]

Evaluate vertical density profile at height z.

Parameters:

z (ndarray) – Height above/below disk midplane in degrees.

Returns:

Density at height z (normalized).

Return type:

ndarray

Notes

This is an abstract method that must be implemented by subclasses.

class socca.models.disk.vertical.HyperSecantHeight(**kwargs)[source]

Bases: Height

Hyperbolic secant vertical density profile.

Models the vertical structure of disk galaxies using a hyperbolic secant (sech) function raised to a power. Commonly used for thick disks.

Parameters:

**kwargs (dict) –

Keyword arguments including:

zsfloat, optional

Scale height in degrees.

alphafloat, optional

Exponent applied to sech function (typically 1 or 2).

incfloat, optional

Inclination angle (rad).

losdepth, losbinsfloat, int, optional

Integration parameters.

Variables:
  • zs (float) – Scale height (deg).

  • alpha (float) – Exponent parameter.

Notes

The profile is defined as:

rho(z) = sech(abs(z)/zs)^alpha

Common cases:

  • alpha = 1: Simple sech profile

  • alpha = 2: sech^2 profile (isothermal disk)

The sech profile is smoother than exponential near the midplane and has more extended wings, making it suitable for modeling thick disks and stellar halos.

__init__(**kwargs)[source]

Initialize a hyperbolic secant height profile.

Parameters:

**kwargs (dict) – Keyword arguments including zs, alpha, inc, losdepth, losbins.

static profile(z, zs, alpha)[source]

Evaluate hyperbolic secant profile at height z.

Parameters:
  • z (ndarray) – Height above/below disk midplane (deg).

  • zs (float) – Scale height (deg).

  • alpha (float) – Exponent parameter.

Returns:

Density at height z: sech(abs(z)/zs)^alpha.

Return type:

ndarray

Notes

Uses absolute value of z to ensure symmetry about the midplane.

class socca.models.disk.vertical.ExponentialHeight(**kwargs)[source]

Bases: Height

Exponential vertical density profile.

Models the vertical structure of thin disk galaxies using an exponential function. This is the simplest and most commonly used vertical profile.

Parameters:

**kwargs (dict) –

Keyword arguments including:

zsfloat, optional

Scale height in degrees.

incfloat, optional

Inclination angle (rad).

losdepth, losbinsfloat, int, optional

Integration parameters.

Variables:

zs (float) – Scale height (deg).

Notes

The profile is defined as:

rho(z) = exp(-abs(z)/zs)

This simple exponential profile is appropriate for thin stellar disks and is the vertical analog of the exponential radial profile. The scale height zs is typically much smaller than the radial scale length.

The exponential profile has a sharp peak at the midplane and falls off more rapidly than sech profiles, making it suitable for thin disks.

__init__(**kwargs)[source]

Initialize an exponential height profile.

Parameters:

**kwargs (dict) – Keyword arguments including zs, inc, losdepth, losbins.

static profile(z, zs)[source]

Evaluate exponential profile at height z.

Parameters:
  • z (ndarray) – Height above/below disk midplane (deg).

  • zs (float) – Scale height (deg).

Returns:

Density at height z: exp(-abs(z)/zs).

Return type:

ndarray

Notes

Uses absolute value of z to ensure symmetry about the midplane.