The `SpatialModel`

class can be used to create RA and Dec positions of photons,
which can be combined with the energies from a `Spectrum`

object to create a
source that can be written to a SIMPUT photon list. Several `SpatialModel`

derivatives are available, which are documented below.

In general, each `SpatialModel`

takes the following information:

- A central RA and Dec for the source
- Some prescription for how the photons should be distributed on the sky in terms of parameters and/or a model function

Each `SpatialModel`

can be used to generate sky coordinates for events, as
described below in Generating Event Coordinates from Spatial Models.

`PointSourceModel`

¶The `PointSourceModel`

generates photon positions for a
point source.

```
from soxs import PointSourceModel
ra0 = 30.0 # source RA in degrees
dec0 = 45.0 # source Dec in degrees
pt_src = PointSourceModel(ra0, dec0)
```

Though this model is trivial, it is constructed in the same way as the other models below for consistency.

The following classes generate azimuthally symmetric models (though see Ellipticity of Radial Source Models) from functions or lookup tables for a surface brightness profile as a function of radius.

`BetaModel`

¶The `BetaModel`

generates photon positions for a
\(\beta\)-model profile, often used to model galaxy clusters. The
functional form of the \(\beta\)-model for a surface brightness
profile is:

\[S(r) = S_0\left[1+\left(\frac{r}{r_c}\right)^2\right]^{(-3\beta+1/2)}\]

where \(S_0\) is the central surface brightness, \(\beta\) is the slope parameter, and \(r_c\) is the core radius. To construct one:

```
from soxs import BetaModel
ra0 = 30.0 # center RA in degrees
dec0 = 45.0 # center Dec in degrees
r_c = 20.0 # the core radius in arc seconds
beta = 2./3. # the beta slope parameter
beta_src = BetaModel(ra0, dec0, r_c, beta)
```

`AnnulusModel`

¶The `AnnulusModel`

can be used to generate photon
positions for a annulus or disk with uniform surface brightness:

```
from soxs import AnnulusModel
ra0 = 30.0 # center RA in degrees
dec0 = 45.0 # center Dec in degrees
r_in = 0.0 # inner radius of shell in arcseconds
r_out = 10.0 # outer radius of shell in arcseconds
ann_src = AnnulusModel(ra0, dec0, r_in, r_out)
```

`RadialFunctionModel`

¶`RadialFunctionModel`

takes as input a central RA,
Dec, and a Python function or callable object to generate an azimuthally
symmetric distribution of photon positions:

```
from soxs import RadialFunctionModel
# A simple inverse square-law surface brightness profile.
# There is no need to normalize it properly, since that
# will be taken care of by the accompanying spectral
# model. r is in arcseconds.
def S_r(r):
return 1.0/(r*r)
ra0 = 100.0 # center RA in degrees
dec0 = -30.0 # center Dec in degrees
my_src = RadialFunctionModel(ra0, dec0, S_r)
```

`RadialArrayModel`

¶`RadialArrayModel`

takes as input a central RA,
Dec, and two NumPy arrays of radius and surface brightness to generate
an azimuthally symmetric distribution of photon positions:

```
from soxs import RadialArrayModel
ra0 = 100.0 # center RA in degrees
dec0 = -30.0 # center Dec in degrees
r = np.linspace(0.0, 100.0, 10000) # binned array of radii in arcseconds
r_s = 100.0 # scale radius of arcseconds
S_r = 1.0/((1.0+r/r_s)**2*(r/r_s)) # the surface brightness array
my_src = RadialArrayModel(ra0, dec0, r, S_r)
```

`RadialFileModel`

¶`RadialFileModel`

takes as input a central RA, Dec,
and an ASCII table of two columns, radius and surface brightness, to
generate an azimuthally symmetric distribution of photon positions:

```
from soxs import RadialFileModel
ra0 = 100.0 # center RA in degrees
dec0 = -30.0 # center Dec in degrees
my_src = RadialFileModel(ra0, dec0, "my_profile.dat")
```

Any of the radial source models listed above take two parameters,
`ellipticity`

and `theta`

, which define the ellipticity of the
model and the orientation of the ellipse, respectively. For example,
to make an elliptical annulus source tilted 45 degrees from the horizontal:

```
from soxs import AnnulusModel
ra0 = 30.0 # center RA in degrees
dec0 = 45.0 # center Dec in degrees
r_in = 10.0 # inner radius of shell in arcseconds
r_out = 30.0 # outer radius of shell in arcseconds
ellipticity = 0.5
theta = 45.0
ann_src = AnnulusModel(ra0, dec0, r_in, r_out, ellipticity=ellipticity)
```

where `ellipticity`

will shrink the annulus (or other shape) in
the y-direction if < 1 or will expand it in the y-direction if > 1.

`RectangleModel`

¶The `RectangleModel`

generates photon positions
on the sky which fill a given rectangle shape, which can be optionally
rotated through an angle:

```
from soxs import RectangleModel
ra0 = 30.0 # center RA in degrees
dec0 = 45.0 # center Dec in degrees
width = 20.0 # width of the rectangle in arcseconds
height = 10.0 # height of the rectangle in arcseconds
theta = 20.0 # rotation angle of the rectangle in degrees
fov_src = RectangleModel(ra0, dec0, fov, theta=theta)
```

Setting either the `width`

or `height`

parameter to 0.0 creates a line source.

The `FillFOVModel`

generates photon positions on
the sky which fill a given field of view:

```
from soxs import FillFOVModel
ra0 = 30.0 # center RA in degrees
dec0 = 45.0 # center Dec in degrees
fov = 20.0 # width of the field of view in arcminutes
fov_src = FillFOVModel(ra0, dec0, fov)
```

This may be useful for creating background-like sources.

To generate coordinates from any `SpatialModel`

, the method
`generate_coords()`

is provided. This method takes
the number of events you wish to generate as a required parameter, and a pseudo
random number generator as an optional parameter. It returns two unitful arrays of
RA and Dec coordinates in degrees:

```
from soxs import BetaModel
ra0 = 30.0 # center RA in degrees
dec0 = 45.0 # center Dec in degrees
r_c = 20.0 # the core radius in arc seconds
beta = 2./3. # the beta slope parameter
beta_src = BetaModel(ra0, dec0, r_c, beta)
# Generate coordinates
prng = 24 # random seed
num_events = 1000000 # number of events to generate
ra, dec = beta_src.generate_coords(num_events, prng=prng)
```

Normally, `generate_coords()`

will not need to be
called by the end-user but will be used “under the hood” in the generation of
a `PhotonList`

as part of a `SimputCatalog`

.
See Working with SIMPUT Catalogs for more information.