Skip to content

Commit 69e6171

Browse files
committed
Add dataclass attributes docstring, add Polarisation class to __init__
1 parent 280c76a commit 69e6171

File tree

3 files changed

+168
-45
lines changed

3 files changed

+168
-45
lines changed

pyvisgen/simulation/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
)
1212
from .observation import Baselines, Observation, ValidBaselineSubset
1313
from .scan import angularDistance, calc_beam, calc_fourier, integrate, jinc, rime
14-
from .visibility import Visibilities, generate_noise, vis_loop
14+
from .visibility import Polarisation, Visibilities, generate_noise, vis_loop
1515

1616
__all__ = [
1717
"Array",
1818
"Baselines",
1919
"Observation",
20+
"Polarisation",
2021
"ValidBaselineSubset",
2122
"Visibilities",
2223
"angularDistance",

pyvisgen/simulation/observation.py

Lines changed: 148 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66
import astropy.units as un
77
import torch
88
from astropy.constants import c
9-
from astropy.coordinates import AltAz, Angle, EarthLocation, SkyCoord, Longitude
9+
from astropy.coordinates import AltAz, Angle, EarthLocation, Longitude, SkyCoord
1010
from astropy.time import Time
1111
from tqdm.autonotebook import tqdm
1212

1313
from pyvisgen.layouts import layouts
1414
from pyvisgen.simulation.array import Array
1515

16-
1716
DEFAULT_POL_KWARGS = {
1817
"delta": 0,
1918
"amp_ratio": 0.5,
@@ -30,6 +29,21 @@
3029

3130
@dataclass
3231
class Baselines:
32+
"""Baselines dataclass.
33+
34+
Attributes
35+
----------
36+
st1 : :func:`~torch.tensor`
37+
st2 : :func:`~torch.tensor`
38+
u : :func:`~torch.tensor`
39+
v : :func:`~torch.tensor`
40+
w : :func:`~torch.tensor`
41+
valid : :func:`~torch.tensor`
42+
time : :func:`~torch.tensor`
43+
q1 : :func:`~torch.tensor`
44+
q2 : :func:`~torch.tensor`
45+
"""
46+
3347
st1: torch.tensor
3448
st2: torch.tensor
3549
u: torch.tensor
@@ -112,6 +126,30 @@ def get_valid_subset(self, num_baselines, device):
112126

113127
@dataclass()
114128
class ValidBaselineSubset:
129+
"""Valid baselines subset dataclass.
130+
131+
Attributes
132+
----------
133+
u_start : :func:`~torch.tensor`
134+
u_stop : :func:`~torch.tensor`
135+
u_valid : :func:`~torch.tensor`
136+
v_start : :func:`~torch.tensor`
137+
v_stop : :func:`~torch.tensor`
138+
v_valid : :func:`~torch.tensor`
139+
w_start : :func:`~torch.tensor`
140+
w_stop : :func:`~torch.tensor`
141+
w_valid : :func:`~torch.tensor`
142+
baseline_nums : :func:`~torch.tensor`
143+
date : :func:`~torch.tensor`
144+
q1_start : :func:`~torch.tensor`
145+
q1_stop : :func:`~torch.tensor`
146+
q1_valid : :func:`~torch.tensor`
147+
q2_start : :func:`~torch.tensor`
148+
q2_stop : :func:`~torch.tensor`
149+
q2_valid : :func:`~torch.tensor`
150+
151+
"""
152+
115153
u_start: torch.tensor
116154
u_stop: torch.tensor
117155
u_valid: torch.tensor
@@ -207,6 +245,74 @@ def _lexsort(self, a, dim=-1):
207245

208246

209247
class Observation:
248+
"""Main observation simulation class.
249+
The :class:`~pyvisgen.simulation.Observation` class
250+
simulates the baselines and time steps during the
251+
observation.
252+
253+
Parameters
254+
----------
255+
src_ra : float
256+
Source right ascension coordinate.
257+
src_dec : float
258+
Source declination coordinate.
259+
start_time : datetime
260+
Observation start time.
261+
scan_duration : int
262+
Scan duration.
263+
num_scans : int
264+
Number of scans.
265+
scan_separation : int
266+
Scan separation.
267+
integration_time : int
268+
Integration time.
269+
ref_frequency : float
270+
Reference frequency.
271+
frequency_offsets : list
272+
Frequency offsets.
273+
bandwidths : list
274+
Frequency bandwidth.
275+
fov : float
276+
Field of view.
277+
image_size : int
278+
Image size of the sky distribution.
279+
array_layout : str
280+
Name of an existing array layout. See :mod:`~pyvisgen.layouts`.
281+
corrupted : bool
282+
If ``True``, apply corruption during the vis loop.
283+
device : str
284+
Torch device to select for computation.
285+
dense : bool, optional
286+
If ``True``, apply dense baseline calculation of a perfect
287+
interferometer. Default: ``False``
288+
sensitivity_cut : float, optional
289+
Sensitivity threshold, where only pixels above the value
290+
are kept. Default: ``1e-6``
291+
polarisation : str, optional
292+
Choose between ``'linear'`` or ``'circular'`` or ``None`` to
293+
simulate different types of polarisations or disable
294+
the simulation of polarisation. Default: ``None``
295+
pol_kwargs : dict, optional
296+
Additional keyword arguments for the simulation
297+
of polarisation. Default:
298+
``{'delta': 0,'amp_ratio': 0.5,'random_state': 42}``
299+
field_kwargs : dict, optional
300+
Additional keyword arguments for the random polarisation
301+
field that is applied when simulating polarisation.
302+
Default:
303+
``{'order': [1, 1],'scale': [0, 1],'threshold': None,'random_state': 42}``
304+
show_progress : bool, optional
305+
If ``True``, show a progress bar during the iteration over the
306+
scans. Default: ``False``
307+
308+
Notes
309+
-----
310+
See :class:`~pyvisgen.simulation.Polarisation` and
311+
:class:`~pyvisgen.simulation.Polarisation.rand_polarisation_field`
312+
for more information on the keyword arguments in ``pol_kwargs``
313+
and ``field_kwargs``, respectively.
314+
"""
315+
210316
def __init__(
211317
self,
212318
src_ra: float,
@@ -260,21 +366,21 @@ def __init__(
260366
image_size : int
261367
Image size of the sky distribution.
262368
array_layout : str
263-
Name of an existing array layout. See `~pyvisgen.layouts`.
369+
Name of an existing array layout. See :mod:`~pyvisgen.layouts`.
264370
corrupted : bool
265-
If `True`, apply corruption during the vis loop.
371+
If ``True``, apply corruption during the vis loop.
266372
device : str
267373
Torch device to select for computation.
268374
dense : bool, optional
269-
If `True`, apply dense baseline calculation of a perfect
270-
interferometer. Default: `False`
375+
If ``True``, apply dense baseline calculation of a perfect
376+
interferometer. Default: ``False``
271377
sensitivity_cut : float, optional
272378
Sensitivity threshold, where only pixels above the value
273-
are kept. Default: 1e-6
379+
are kept. Default: ``1e-6``
274380
polarisation : str, optional
275-
Choose between `'linear'` or `'circular'` or `None` to
381+
Choose between ``'linear'`` or ``'circular'`` or ``None`` to
276382
simulate different types of polarisations or disable
277-
the simulation of polarisation. Default: `None`
383+
the simulation of polarisation. Default: ``None``
278384
pol_kwargs : dict, optional
279385
Additional keyword arguments for the simulation
280386
of polarisation. Default: `{
@@ -292,15 +398,15 @@ def __init__(
292398
"random_state": 42
293399
}`
294400
show_progress : bool, optional
295-
If `True`, show a progress bar during the iteration over the
296-
scans. Default: False
401+
If ``True``, show a progress bar during the iteration over the
402+
scans. Default: ``False``
297403
298404
Notes
299405
-----
300-
See `~pyvisgen.simulation.visibility.Polarisation` and
301-
`~pyvisgen.simulation.visibility.Polarisation.rand_polarisation_field`
302-
for more information on the keyword arguments in `pol_kwargs`
303-
and `field_kwargs`, respectively.
406+
See :class:`~pyvisgen.simulation.Polarisation` and
407+
:class:`~pyvisgen.simulation.Polarisation.rand_polarisation_field`
408+
for more information on the keyword arguments in ``pol_kwargs``
409+
and ``field_kwargs``, respectively.
304410
"""
305411
self.ra = torch.tensor(src_ra).double()
306412
self.dec = torch.tensor(src_dec).double()
@@ -396,6 +502,10 @@ def calc_time_steps(self):
396502
return time, time.mjd * (60 * 60 * 24)
397503

398504
def calc_dense_baselines(self):
505+
"""Calculates the baselines of a densely-built
506+
antenna array, which would provide full coverage of the
507+
uv space.
508+
"""
399509
N = self.img_size
400510
fov = self.fov * pi / (3600 * 180)
401511
delta = fov ** (-1) * c.value / self.ref_frequency
@@ -437,9 +547,11 @@ def calc_dense_baselines(self):
437547
)
438548

439549
def calc_baselines(self):
440-
"""Initializes Baselines dataclass object and
441-
calls self.get_baselines to compute the contents of
442-
the Baselines dataclass.
550+
"""Initializes :class:`~pyvisgen.simulation.Baselines`
551+
dataclass object and calls
552+
:py:func:`~pyvisgen.simulation.Observation.get_baselines`
553+
to compute the contents of the :class:`~pyvisgen.simulation.Baselines`
554+
dataclass.
443555
"""
444556
self.baselines = Baselines(
445557
torch.tensor([]), # st1
@@ -534,7 +646,22 @@ def get_baselines(self, times):
534646

535647
return baselines
536648

537-
def calc_ref_elev(self, time=None):
649+
def calc_ref_elev(self, time=None) -> tuple:
650+
"""Calculates the station elevations for given
651+
time steps.
652+
653+
Parameters
654+
----------
655+
time : array_like or None, optional
656+
Array containing observation time steps.
657+
Default: ``None``
658+
659+
Returns
660+
-------
661+
tuple
662+
Tuple containing tensors of the Greenwich hour angle,
663+
antenna-local hour angles, and the elevations.
664+
"""
538665
if time is None:
539666
time = self.times
540667
if time.shape == ():
@@ -592,7 +719,8 @@ def calc_feed_rotation(self, ha: Angle) -> Angle:
592719
593720
.. math::
594721
595-
q = \atan\left(\frac{\sin h}{\cos\delta \tan\varphi - \sin\delta \cos h\right),
722+
q = \atan\left(\frac{\sin h}{\cos\delta
723+
\tan\varphi - \sin\delta \cos h\right),
596724
597725
where $h$ is the local hour angle, $\varphi$ the geographical latitude
598726
of the observer, and $\delta$ the declination of the source.
@@ -612,30 +740,6 @@ def calc_feed_rotation(self, ha: Angle) -> Angle:
612740

613741
return q
614742

615-
def calc_direction_cosines(self, ha, el_st, delta_x, delta_y, delta_z):
616-
src_dec = torch.deg2rad(self.dec)
617-
ha = torch.deg2rad(ha)
618-
619-
u = (torch.sin(ha) * delta_x + torch.cos(ha) * delta_y).reshape(-1)
620-
v = (
621-
-torch.sin(src_dec) * torch.cos(ha) * delta_x
622-
+ torch.sin(src_dec) * torch.sin(ha) * delta_y
623-
+ torch.cos(src_dec) * delta_z
624-
).reshape(-1)
625-
w = (
626-
torch.cos(src_dec) * torch.cos(ha) * delta_x
627-
- torch.cos(src_dec) * torch.sin(ha) * delta_y
628-
+ torch.sin(src_dec) * delta_z
629-
).reshape(-1)
630-
631-
if not (u.shape == v.shape == w.shape):
632-
raise ValueError(
633-
"Expected u, v, and w to have the same shapes: "
634-
f"{u.shape}, {v.shape}, {w.shape}"
635-
)
636-
637-
return u, v, w
638-
639743
def create_rd_grid(self):
640744
"""Calculates RA and Dec values for a given fov around a source position
641745

pyvisgen/simulation/visibility.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@
1010

1111
@dataclass
1212
class Visibilities:
13+
"""Visibilities dataclass.
14+
15+
Attributes
16+
----------
17+
V_11 : :func:`~torch.tensor`
18+
V_22 : :func:`~torch.tensor`
19+
V_12 : :func:`~torch.tensor`
20+
V_21 : :func:`~torch.tensor`
21+
num : :func:`~torch.tensor`
22+
base_num : :func:`~torch.tensor`
23+
u : :func:`~torch.tensor`
24+
v : :func:`~torch.tensor`
25+
w : :func:`~torch.tensor`
26+
date : :func:`~torch.tensor`
27+
linear_dop : :func:`~torch.tensor`
28+
circular_dop : :func:`~torch.tensor`
29+
"""
30+
1331
V_11: torch.tensor
1432
V_22: torch.tensor
1533
V_12: torch.tensor

0 commit comments

Comments
 (0)