Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: only add Trx bias to autocorr noise #212

Merged
merged 6 commits into from
Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@
Changelog
=========

v2.3.2 [2022.02.18]
===================

Added
-----
- ``_extract_kwargs`` attribute added to the ``SimulationComponent`` class. This
attribute is used by the ``Simulator`` to determine which optional parameters
should actually be extracted from the data.
- ``antpair`` optional parameter added to the ``ThermalNoise`` class. This is
used to determine whether to simulate noise via the radiometer equation (as is
appropriate for a cross-correlation) or to just add a bias from the receiver
temperature (which is our proxy for what should happen to an auto-correlation).

Fixed
-----
- The ``Simulator`` class now correctly uses the auto-correlations to simulate
noise for the cross-correlations.

v2.3.1 [2022.01.19]
===================

Expand Down
3 changes: 3 additions & 0 deletions hera_sim/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class determine how to apply the effect simulated by

_alias: Tuple[str] = tuple()

# Keyword arguments for the Simulator to extract from the data
_extract_kwargs = set()

def __init_subclass__(cls, is_abstract: bool = False):
"""Provide some useful augmentations to subclasses.

Expand Down
24 changes: 23 additions & 1 deletion hera_sim/noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,21 @@ class ThermalNoise(Noise):
Receiver temperature in K
autovis : float, optional
Autocorrelation visibility amplitude. Used if provided instead of ``Tsky_mdl``.
antpair : tuple of int, optional
Antenna numbers for the baseline that noise is being simulated for. This is
just used to determine whether to simulate noise via the radiometer equation
or to just add a bias from the receiver temperature.

Notes
-----
At the time of writing, we're unsure of the correct prescription for
autocorrelations, so we only add a receiver temperature bias to baselines that
are interpreted as autocorrelations (i.e. where the ``bl_vec`` parameter provided
on calling an instance of this class is nearly zero length).
"""

_alias = ("thermal_noise",)
_extract_kwargs = {"autovis", "antpair"}

def __init__(
self,
Expand All @@ -56,6 +68,7 @@ def __init__(
channel_width=None,
Trx=0,
autovis=None,
antpair=None,
):
super().__init__(
Tsky_mdl=Tsky_mdl,
Expand All @@ -64,6 +77,7 @@ def __init__(
channel_width=channel_width,
Trx=Trx,
autovis=autovis,
antpair=antpair,
)

def __call__(self, lsts: np.ndarray, freqs: np.ndarray, **kwargs):
Expand All @@ -79,7 +93,9 @@ def __call__(self, lsts: np.ndarray, freqs: np.ndarray, **kwargs):
Returns
-------
array
A 2D array shaped ``(lsts, freqs)`` with the thermal noise.
A 2D array shaped ``(lsts, freqs)`` with the thermal noise. If the
provided ``antpair`` is for an autocorrelation, then only a receiver
temperature bias is returned.
"""
# validate the kwargs
self._check_kwargs(**kwargs)
Expand All @@ -92,6 +108,7 @@ def __call__(self, lsts: np.ndarray, freqs: np.ndarray, **kwargs):
channel_width,
Trx,
autovis,
antpair,
) = self._extract_kwarg_values(**kwargs)

# get the channel width in Hz if not specified
Expand All @@ -113,6 +130,11 @@ def __call__(self, lsts: np.ndarray, freqs: np.ndarray, **kwargs):
if callable(omega_p):
omega_p = omega_p(freqs)

# If this is an autocorrelation, only add receiver temperature bias
if antpair is not None:
if antpair[0] == antpair[1]:
return Trx / utils.jansky_to_kelvin(freqs, omega_p).reshape(1, -1)

# get the sky temperature; use an autocorrelation if provided
if autovis is not None and not np.all(np.isclose(autovis, 0)):
Tsky = autovis * utils.jansky_to_kelvin(freqs, omega_p).reshape(1, -1)
Expand Down
6 changes: 5 additions & 1 deletion hera_sim/simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,11 @@ def func(freqs, ants, other=None):
has a default value, it will not be in the returned dictionary.
"""
model_params = self._get_model_parameters(model)
model_params = {k: v for k, v in model_params.items() if v is inspect._empty}
model_params = {
k: v
for k, v in model_params.items()
if v is inspect._empty or k in model._extract_kwargs
}

# Pull the LST and frequency arrays if they are required.
# TODO: update this to allow more flexibility in which arguments are
Expand Down
2 changes: 1 addition & 1 deletion hera_sim/tests/test_beams.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def run_sim(
use_pixel_beams=use_pixel_beams,
use_gpu=use_gpu,
mpi_comm=DummyMPIComm() if use_mpi else None,
bm_pix=200,
bm_pix=201,
precision=2,
)

Expand Down
11 changes: 6 additions & 5 deletions hera_sim/tests/test_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,16 @@ def test_get_with_one_seed(base_sim, pol, conj):
# TODO: this will need to be updated when full polarization support is added
@pytest.mark.parametrize("pol", [None, "xx"])
@pytest.mark.parametrize("conj", [True, False])
def test_get_with_initial_seed(base_sim, pol, conj):
def test_get_with_initial_seed(pol, conj):
# Simulate an effect where we would actually use this setting.
base_sim.add("thermal_noise", seed="initial")
sim = create_sim(autos=True)
sim.add("thermal_noise", seed="initial")
ant1, ant2 = (0, 1) if conj else (1, 0)
vis = base_sim.get("thermal_noise", key=(ant1, ant2, pol))
vis = sim.get("thermal_noise", key=(ant1, ant2, pol))
if pol:
assert np.allclose(base_sim.data.get_data(ant1, ant2, pol), vis)
assert np.allclose(sim.data.get_data(ant1, ant2, pol), vis)
else:
assert np.allclose(base_sim.data.get_data(ant1, ant2), vis[..., 0])
assert np.allclose(sim.data.get_data(ant1, ant2), vis[..., 0])


def test_get_nonexistent_component(ref_sim):
Expand Down
2 changes: 1 addition & 1 deletion hera_sim/visibilities/vis_cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class VisCPU(VisibilitySimulator):

def __init__(
self,
bm_pix: int = 100,
bm_pix: int = 101,
use_pixel_beams: bool = True,
precision: int = 1,
use_gpu: bool = False,
Expand Down