-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from lincc-frameworks/galaxies
Create the ability to sample from a background model
- Loading branch information
Showing
3 changed files
with
172 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import numpy as np | ||
from astropy.coordinates import angular_separation | ||
|
||
from tdastro.base_models import PhysicalModel | ||
|
||
|
||
class GaussianGalaxy(PhysicalModel): | ||
"""A static source. | ||
Attributes | ||
---------- | ||
radius_std : `float` | ||
The standard deviation of the brightness as we move away | ||
from the galaxy's center (in degrees). | ||
brightness : `float` | ||
The inherent brightness at the center of the galaxy. | ||
""" | ||
|
||
def __init__(self, brightness, radius, **kwargs): | ||
super().__init__(**kwargs) | ||
self.add_parameter("galaxy_radius_std", radius, required=True, **kwargs) | ||
self.add_parameter("brightness", brightness, required=True, **kwargs) | ||
|
||
def __str__(self): | ||
"""Return the string representation of the model.""" | ||
return f"GuassianGalaxy({self.brightness}, {self.galaxy_radius_std})" | ||
|
||
def sample_ra(self): | ||
"""Sample an right ascension coordinate based on the center and radius of the galaxy. | ||
Returns | ||
------- | ||
ra : `float` | ||
The sampled right ascension in degrees. | ||
""" | ||
return np.random.normal(loc=self.ra, scale=self.galaxy_radius_std) | ||
|
||
def sample_dec(self): | ||
"""Sample a declination coordinate based on the center and radius of the galaxy. | ||
Returns | ||
------- | ||
dec : `float` | ||
The sampled declination in degrees. | ||
""" | ||
return np.random.normal(loc=self.dec, scale=self.galaxy_radius_std) | ||
|
||
def _evaluate(self, times, wavelengths, ra=None, dec=None, **kwargs): | ||
"""Draw effect-free observations for this object. | ||
Parameters | ||
---------- | ||
times : `numpy.ndarray` | ||
A length T array of timestamps. | ||
wavelengths : `numpy.ndarray`, optional | ||
A length N array of wavelengths. | ||
ra : `float`, optional | ||
The right ascension of the observations in degrees. | ||
dec : `float`, optional | ||
The declination of the observations in degrees. | ||
**kwargs : `dict`, optional | ||
Any additional keyword arguments. | ||
Returns | ||
------- | ||
flux_density : `numpy.ndarray` | ||
A length T x N matrix of SED values. | ||
""" | ||
if ra is None: | ||
ra = self.ra | ||
if dec is None: | ||
dec = self.dec | ||
|
||
# Scale the brightness as a Guassian function centered on the object's RA and Dec. | ||
dist = angular_separation( | ||
self.ra * np.pi / 180.0, | ||
self.dec * np.pi / 180.0, | ||
ra * np.pi / 180.0, | ||
dec * np.pi / 180.0, | ||
) | ||
scale = np.exp(-(dist * dist) / (2.0 * self.galaxy_radius_std * self.galaxy_radius_std)) | ||
|
||
return np.full((len(times), len(wavelengths)), self.brightness * scale) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import random | ||
|
||
import numpy as np | ||
from tdastro.sources.galaxy_models import GaussianGalaxy | ||
from tdastro.sources.static_source import StaticSource | ||
|
||
|
||
def _sample_ra(**kwargs): | ||
"""Return a random value between 0 and 360. | ||
Parameters | ||
---------- | ||
**kwargs : `dict`, optional | ||
Absorbs additional parameters | ||
""" | ||
return 360.0 * random.random() | ||
|
||
|
||
def _sample_dec(**kwargs): | ||
"""Return a random value between -90 and 90. | ||
Parameters | ||
---------- | ||
**kwargs : `dict`, optional | ||
Absorbs additional parameters | ||
""" | ||
return 180.0 * random.random() - 90.0 | ||
|
||
|
||
def test_gaussian_galaxy() -> None: | ||
"""Test that we can sample and create a StaticSource object.""" | ||
random.seed(1001) | ||
|
||
host = GaussianGalaxy(ra=_sample_ra, dec=_sample_dec, brightness=10.0, radius=1.0 / 3600.0) | ||
host_ra = host.ra | ||
host_dec = host.dec | ||
|
||
source = StaticSource(ra=host.sample_ra, dec=host.sample_dec, background=host, brightness=100.0) | ||
|
||
# Both RA and dec should be "close" to (but not exactly at) the center of the galaxy. | ||
source_ra_offset = source.ra - host_ra | ||
assert 0.0 < np.abs(source_ra_offset) < 100.0 / 3600.0 | ||
|
||
source_dec_offset = source.dec - host_dec | ||
assert 0.0 < np.abs(source_dec_offset) < 100.0 / 3600.0 | ||
|
||
times = np.array([1, 2, 3, 4, 5, 10]) | ||
wavelengths = np.array([100.0, 200.0, 300.0]) | ||
|
||
# All the measured fluxes should have some contribution from the background object. | ||
values = source.evaluate(times, wavelengths) | ||
assert values.shape == (6, 3) | ||
assert np.all(values > 100.0) | ||
assert np.all(values <= 110.0) | ||
|
||
# Check that if we resample the source it will propagate and correctly resample the host. | ||
# the host's (RA, dec) should change and the source's should still be close. | ||
source.sample_parameters() | ||
assert host_ra != host.ra | ||
assert host_dec != host.dec | ||
|
||
source_ra_offset2 = source.ra - host.ra | ||
assert source_ra_offset != source_ra_offset2 | ||
assert 0.0 < np.abs(source_ra_offset2) < 100.0 / 3600.0 | ||
|
||
source_dec_offset2 = source.dec - host.dec | ||
assert source_dec_offset != source_dec_offset2 | ||
assert 0.0 < np.abs(source_ra_offset2) < 100.0 / 3600.0 |