tabsim 0.0.1__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tabsim-0.0.1 → tabsim-0.0.3}/PKG-INFO +11 -1
- {tabsim-0.0.1 → tabsim-0.0.3}/README.md +5 -0
- tabsim-0.0.3/docs/conf.py +14 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/pyproject.toml +3 -1
- tabsim-0.0.3/tabsim/__init__.py +6 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/config.py +11 -9
- tabsim-0.0.3/tabsim/data/aux_data/tles/2023-02-21-J8HE0T.json +1 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/jax/coordinates.py +255 -1
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/scripts/sim_vis.py +10 -1
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/sky.py +3 -1
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/tle.py +6 -4
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/write.py +39 -3
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim.egg-info/PKG-INFO +11 -1
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim.egg-info/SOURCES.txt +6 -1
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim.egg-info/requires.txt +7 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim.egg-info/top_level.txt +2 -0
- tabsim-0.0.3/tests/test_basic.py +5 -0
- tabsim-0.0.3/tests/test_sim-vis.py +40 -0
- tabsim-0.0.3/tests/test_version.py +6 -0
- tabsim-0.0.1/tabsim/jax/__init__.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/LICENSE +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/setup.cfg +0 -0
- {tabsim-0.0.1/tabsim → tabsim-0.0.3/tabsim/dask}/__init__.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/dask/coordinates.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/dask/extras.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/dask/interferometry.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/dask/observation.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/EDA2.itrf.txt +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/MWA.itrf.txt +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/MeerKAT.itrf.txt +0 -0
- {tabsim-0.0.1/tabsim/dask → tabsim-0.0.3/tabsim/data}/__init__.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/aux_data/calibrator.skymodel +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/aux_data/norad_satellite.rfimodel +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/aux_data/satellite.ole +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/aux_data/satellite.rfimodel +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/aux_data/stationary.loc +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/aux_data/stationary.rfimodel +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/config_files/sim_config_base.yaml +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/data/config_files/tab_config_base.yaml +0 -0
- {tabsim-0.0.1/tabsim/data → tabsim-0.0.3/tabsim/jax}/__init__.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/jax/interferometry.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/jax/utils.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/plot.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/scripts/__init__.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/scripts/ast_region.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/scripts/flag_data.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/scripts/tle_sat_region.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim/tools.py +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim.egg-info/dependency_links.txt +0 -0
- {tabsim-0.0.1 → tabsim-0.0.3}/tabsim.egg-info/entry_points.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tabsim
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Trajectory-based Radio Frequency Interference (RFI) simulations for radio interferometeric data.
|
|
5
5
|
Author-email: Chris Finlay <christopher.finlay@epfl.ch>
|
|
6
6
|
Maintainer-email: Chris Finlay <christopher.finlay@epfl.ch>
|
|
@@ -702,12 +702,18 @@ Requires-Dist: regions; extra == "sat"
|
|
|
702
702
|
Provides-Extra: ipy
|
|
703
703
|
Requires-Dist: ipython; extra == "ipy"
|
|
704
704
|
Requires-Dist: ipykernel; extra == "ipy"
|
|
705
|
+
Provides-Extra: test
|
|
706
|
+
Requires-Dist: pytest; extra == "test"
|
|
707
|
+
Provides-Extra: docs
|
|
708
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
709
|
+
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
705
710
|
Dynamic: license-file
|
|
706
711
|
|
|
707
712
|
# tab-sim
|
|
708
713
|
|
|
709
714
|
[](https://doi.org/10.1093/mnras/stad1979)
|
|
710
715
|
[](https://doi.org/10.48550/arXiv.2502.00106)
|
|
716
|
+
[](https://tab-sim.readthedocs.io/en/latest/?badge=latest)
|
|
711
717
|
|
|
712
718
|
**T**r**A**jectory **B**ased RFI **Sim**ulations of radio interferometry data.
|
|
713
719
|
A source to visibility model for RFI sources including certain near-field effects.
|
|
@@ -715,6 +721,10 @@ A source to visibility model for RFI sources including certain near-field effect
|
|
|
715
721
|
`tab-sim` is written in [JAX](https://jax.readthedocs.io/en/latest/notebooks/quickstart.html)
|
|
716
722
|
and [Dask](https://www.dask.org) and can therefore use GPUs and/or CPUs to perform larger than memory computation.
|
|
717
723
|
|
|
724
|
+
## Documentation
|
|
725
|
+
|
|
726
|
+
[https://tab-sim.readthedocs.io/](https://tab-sim.readthedocs.io/)
|
|
727
|
+
|
|
718
728
|
## Installation
|
|
719
729
|
|
|
720
730
|
The following instructions are expected to work on Linux machine. If you are running Windows it is recommended to use WSL. If you are running Mac then it is best to start with a [conda](https://docs.conda.io/en/latest/)/[mamba](https://mamba.readthedocs.io/en/latest/index.html) environment and install `python-casacore` before continuing with the `pip` install method. If all else fails there is the [Docker install](#docker).
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://doi.org/10.1093/mnras/stad1979)
|
|
4
4
|
[](https://doi.org/10.48550/arXiv.2502.00106)
|
|
5
|
+
[](https://tab-sim.readthedocs.io/en/latest/?badge=latest)
|
|
5
6
|
|
|
6
7
|
**T**r**A**jectory **B**ased RFI **Sim**ulations of radio interferometry data.
|
|
7
8
|
A source to visibility model for RFI sources including certain near-field effects.
|
|
@@ -9,6 +10,10 @@ A source to visibility model for RFI sources including certain near-field effect
|
|
|
9
10
|
`tab-sim` is written in [JAX](https://jax.readthedocs.io/en/latest/notebooks/quickstart.html)
|
|
10
11
|
and [Dask](https://www.dask.org) and can therefore use GPUs and/or CPUs to perform larger than memory computation.
|
|
11
12
|
|
|
13
|
+
## Documentation
|
|
14
|
+
|
|
15
|
+
[https://tab-sim.readthedocs.io/](https://tab-sim.readthedocs.io/)
|
|
16
|
+
|
|
12
17
|
## Installation
|
|
13
18
|
|
|
14
19
|
The following instructions are expected to work on Linux machine. If you are running Windows it is recommended to use WSL. If you are running Mac then it is best to start with a [conda](https://docs.conda.io/en/latest/)/[mamba](https://mamba.readthedocs.io/en/latest/index.html) environment and install `python-casacore` before continuing with the `pip` install method. If all else fails there is the [Docker install](#docker).
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
sys.path.insert(0, os.path.abspath('..'))
|
|
4
|
+
|
|
5
|
+
project = 'tab‑sim'
|
|
6
|
+
author = 'Chris Finlay'
|
|
7
|
+
extensions = [
|
|
8
|
+
'sphinx.ext.autodoc',
|
|
9
|
+
'sphinx.ext.napoleon',
|
|
10
|
+
'sphinx.ext.viewcode',
|
|
11
|
+
]
|
|
12
|
+
templates_path = ['_templates']
|
|
13
|
+
exclude_patterns = []
|
|
14
|
+
html_theme = 'sphinx_rtd_theme'
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "tabsim"
|
|
8
|
-
version = "0.0.
|
|
8
|
+
version = "0.0.3"
|
|
9
9
|
license = {file = "LICENSE"}
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
# dynamic = ["version", "readme"]
|
|
@@ -31,6 +31,8 @@ sat = ["regions"]
|
|
|
31
31
|
# all = ["jax[cuda12]", "regions", "bdsf", "TGEpy @ git+https://github.com/chrisfinlay/TGEpy.git"]
|
|
32
32
|
# all_cpu = ["regions", "bdsf", "TGEpy @ git+https://github.com/chrisfinlay/TGEpy.git"]
|
|
33
33
|
ipy = ["ipython", "ipykernel"]
|
|
34
|
+
test = ["pytest"]
|
|
35
|
+
docs = ["sphinx", "sphinx-rtd-theme"]
|
|
34
36
|
|
|
35
37
|
[project.urls]
|
|
36
38
|
Repository = "https://github.com/chrisfinlay/tab-sim.git"
|
|
@@ -5,7 +5,8 @@ import sys
|
|
|
5
5
|
import shutil
|
|
6
6
|
|
|
7
7
|
import collections.abc
|
|
8
|
-
from typing import Tuple
|
|
8
|
+
from typing import Tuple, Union, Optional
|
|
9
|
+
|
|
9
10
|
from datetime import datetime
|
|
10
11
|
|
|
11
12
|
import dask.array as da
|
|
@@ -13,13 +14,14 @@ from dask.array.core import Array
|
|
|
13
14
|
import xarray as xr
|
|
14
15
|
import numpy as np
|
|
15
16
|
import pandas as pd
|
|
17
|
+
from astropy.time import Time
|
|
16
18
|
|
|
17
19
|
from tabsim.dask.observation import Observation
|
|
18
20
|
from tabsim.sky import generate_random_sky
|
|
19
21
|
from tabsim.plot import plot_uv, plot_src_alt, plot_angular_seps
|
|
20
22
|
from tabsim.write import write_ms, mk_obs_name, mk_obs_dir
|
|
21
|
-
from tabsim.jax.coordinates import calculate_fringe_frequency
|
|
22
|
-
from tabsim.tle import get_visible_satellite_tles
|
|
23
|
+
from tabsim.jax.coordinates import calculate_fringe_frequency, jd_to_mjd
|
|
24
|
+
from tabsim.tle import get_visible_satellite_tles, id_generator
|
|
23
25
|
|
|
24
26
|
from daskms import xds_from_ms
|
|
25
27
|
|
|
@@ -188,7 +190,7 @@ def load_sky_model(file_path: str, freqs: Array, src_type: str) -> tuple:
|
|
|
188
190
|
raise KeyError("'src_type' must be one of {'point', 'gauss', 'exp'}.")
|
|
189
191
|
|
|
190
192
|
|
|
191
|
-
def sigma_value(value: str
|
|
193
|
+
def sigma_value(value: Union[str, float, int], obs: Observation):
|
|
192
194
|
try:
|
|
193
195
|
if isinstance(value, str):
|
|
194
196
|
sigma = (np.mean(obs.noise_std) / np.sqrt(obs.n_time * obs.n_bl)).compute()
|
|
@@ -212,12 +214,9 @@ def load_obs(obs_spec: dict) -> Observation:
|
|
|
212
214
|
return x
|
|
213
215
|
|
|
214
216
|
if obs_["start_time_jd"]:
|
|
215
|
-
from tabascal.jax.coordinates import jd_to_mjd
|
|
216
217
|
|
|
217
218
|
start_time_mjd = jd_to_mjd(obs_["start_time_jd"])
|
|
218
219
|
elif obs_["start_time_isot"]:
|
|
219
|
-
from astropy.time import Time
|
|
220
|
-
from tabascal.jax.coordinates import jd_to_mjd
|
|
221
220
|
|
|
222
221
|
start_time_mjd = jd_to_mjd(
|
|
223
222
|
Time(obs_["start_time_isot"], format="isot", scale="ut1").jd
|
|
@@ -837,11 +836,14 @@ def print_fringe_freq_tle_sat(obs: Observation):
|
|
|
837
836
|
|
|
838
837
|
|
|
839
838
|
def run_sim_config(
|
|
840
|
-
obs_spec: dict = None,
|
|
839
|
+
obs_spec: Optional[dict] = None,
|
|
840
|
+
config_path: Optional[str] = None,
|
|
841
|
+
spacetrack_path: Optional[str] = None,
|
|
841
842
|
) -> Tuple[Observation, str]:
|
|
842
843
|
|
|
843
844
|
from tabsim.tle import id_generator
|
|
844
845
|
|
|
846
|
+
|
|
845
847
|
log_path = f"log_sim_{id_generator()}.txt"
|
|
846
848
|
log = open(log_path, "w")
|
|
847
849
|
backup = sys.stdout
|
|
@@ -859,7 +861,7 @@ def run_sim_config(
|
|
|
859
861
|
obs = load_obs(obs_spec)
|
|
860
862
|
add_astro_sources(obs, obs_spec)
|
|
861
863
|
add_satellite_sources(obs, obs_spec)
|
|
862
|
-
if obs_spec["rfi_sources"]["tle_satellite"]["max_n_sat"] != 0:
|
|
864
|
+
if obs_spec["rfi_sources"]["tle_satellite"]["max_n_sat"] != 0 and spacetrack_path:
|
|
863
865
|
add_tle_satellite_sources(obs, obs_spec, spacetrack_path)
|
|
864
866
|
add_stationary_sources(obs, obs_spec)
|
|
865
867
|
add_gains(obs, obs_spec)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"COMMENT":{"0":"GENERATED VIA SPACETRACK.ORG API","1":"GENERATED VIA SPACETRACK.ORG API","2":"GENERATED VIA SPACETRACK.ORG API","3":"GENERATED VIA SPACETRACK.ORG API","4":"GENERATED VIA SPACETRACK.ORG API","5":"GENERATED VIA SPACETRACK.ORG API","6":"GENERATED VIA SPACETRACK.ORG API","7":"GENERATED VIA SPACETRACK.ORG API"},"ORIGINATOR":{"0":"18 SPCS","1":"18 SPCS","2":"18 SPCS","3":"18 SPCS","4":"18 SPCS","5":"18 SPCS","6":"18 SPCS","7":"18 SPCS"},"NORAD_CAT_ID":{"0":"20452","1":"38833","2":"38833","3":"38833","4":"38833","5":"45854","6":"45854","7":"45854"},"OBJECT_NAME":{"0":"NAVSTAR 18 (USA 50)","1":"NAVSTAR 67 (USA 239)","2":"NAVSTAR 67 (USA 239)","3":"NAVSTAR 67 (USA 239)","4":"NAVSTAR 67 (USA 239)","5":"NAVSTAR 79 (USA 304)","6":"NAVSTAR 79 (USA 304)","7":"NAVSTAR 79 (USA 304)"},"OBJECT_TYPE":{"0":"PAYLOAD","1":"PAYLOAD","2":"PAYLOAD","3":"PAYLOAD","4":"PAYLOAD","5":"PAYLOAD","6":"PAYLOAD","7":"PAYLOAD"},"CLASSIFICATION_TYPE":{"0":"U","1":"U","2":"U","3":"U","4":"U","5":"U","6":"U","7":"U"},"INTLDES":{"0":"90008A","1":"12053A","2":"12053A","3":"12053A","4":"12053A","5":"20041A","6":"20041A","7":"20041A"},"EPOCH":{"0":"2023-02-21 06:38:50","1":"2023-02-21 06:37:41","2":"2023-02-21 06:37:41","3":"2023-02-21 06:37:41","4":"2023-02-22 06:33:35","5":"2023-02-21 08:40:26","6":"2023-02-22 10:18:13","7":"2023-02-22 10:18:13"},"EPOCH_MICROSECONDS":{"0":"12736","1":"186496","2":"186496","3":"189952","4":"104608","5":"76288","6":"882176","7":"882176"},"MEAN_MOTION":{"0":"1.89597679","1":"2.0056438","2":"2.0056438","3":"2.00564379","4":"2.00564407","5":"2.00566443","6":"2.00566487","7":"2.00566487"},"ECCENTRICITY":{"0":"0.0013992","1":"0.0135647","2":"0.0135647","3":"0.013565","4":"0.0135663","5":"0.0030268","6":"0.0030262","7":"0.0030262"},"INCLINATION":{"0":"54.7164","1":"53.518","2":"53.518","3":"53.518","4":"53.5179","5":"55.7203","6":"55.7213","7":"55.7213"},"RA_OF_ASC_NODE":{"0":"175.9594","1":"193.1658","2":"193.1658","3":"193.1658","4":"193.125","5":"76.4335","6":"76.391","7":"76.391"},"ARG_OF_PERICENTER":{"0":"264.8777","1":"50.1444","2":"50.1444","3":"50.1442","4":"50.1485","5":"186.8094","6":"186.8192","7":"186.8192"},"MEAN_ANOMALY":{"0":"93.0539","1":"310.9883","2":"310.9883","3":"310.9885","4":"310.9878","5":"299.724","6":"350.8122","7":"350.8122"},"EPHEMERIS_TYPE":{"0":"0","1":"0","2":"0","3":"0","4":"0","5":"0","6":"0","7":"0"},"ELEMENT_SET_NO":{"0":"999","1":"999","2":"999","3":"999","4":"999","5":"999","6":"999","7":"999"},"REV_AT_EPOCH":{"0":"23344","1":"7602","2":"7513","3":"7513","4":"7515","5":"1973","6":"1974","7":"1975"},"BSTAR":{"0":"0","1":"0","2":"0","3":"0","4":"0","5":"0","6":"0","7":"0"},"MEAN_MOTION_DOT":{"0":"0.00000009","1":"0.00000013","2":"0.00000013","3":"0.00000013","4":"0.0000002","5":"-0.00000013","6":"-0.00000024","7":"-0.00000024"},"MEAN_MOTION_DDOT":{"0":"0","1":"0","2":"0","3":"0","4":"0","5":"0","6":"0","7":"0"},"FILE":{"0":"3819803","1":"3818603","2":"3819803","3":"3821329","4":"3824148","5":"3821329","6":"3823581","7":"3824148"},"TLE_LINE0":{"0":"0 NAVSTAR 18 (USA 50)","1":"0 NAVSTAR 67 (USA 239)","2":"0 NAVSTAR 67 (USA 239)","3":"0 NAVSTAR 67 (USA 239)","4":"0 NAVSTAR 67 (USA 239)","5":"0 NAVSTAR 79 (USA 304)","6":"0 NAVSTAR 79 (USA 304)","7":"0 NAVSTAR 79 (USA 304)"},"TLE_LINE1":{"0":"1 20452U 90008A 23052.27696774 .00000009 00000-0 00000-0 0 9999","1":"1 38833U 12053A 23052.27617114 .00000013 00000-0 00000+0 0 9990","2":"1 38833U 12053A 23052.27617114 .00000013 00000-0 00000-0 0 9991","3":"1 38833U 12053A 23052.27617118 .00000013 00000-0 00000-0 0 9995","4":"1 38833U 12053A 23053.27332297 .00000020 00000-0 00000-0 0 9996","5":"1 45854U 20041A 23052.36141292 -.00000013 00000-0 00000-0 0 9998","6":"1 45854U 20041A 23053.42932734 -.00000024 00000-0 00000+0 0 9996","7":"1 45854U 20041A 23053.42932734 -.00000024 00000-0 00000-0 0 9997"},"TLE_LINE2":{"0":"2 20452 54.7164 175.9594 0013992 264.8777 93.0539 1.89597679233443","1":"2 38833 53.5180 193.1658 0135647 50.1444 310.9883 2.00564380 76021","2":"2 38833 53.5180 193.1658 0135647 50.1444 310.9883 2.00564380 75132","3":"2 38833 53.5180 193.1658 0135650 50.1442 310.9885 2.00564379 75134","4":"2 38833 53.5179 193.1250 0135663 50.1485 310.9878 2.00564407 75157","5":"2 45854 55.7203 76.4335 0030268 186.8094 299.7240 2.00566443 19736","6":"2 45854 55.7213 76.3910 0030262 186.8192 350.8122 2.00566487 19745","7":"2 45854 55.7213 76.3910 0030262 186.8192 350.8122 2.00566487 19756"},"OBJECT_ID":{"0":"1990-008A","1":"2012-053A","2":"2012-053A","3":"2012-053A","4":"2012-053A","5":"2020-041A","6":"2020-041A","7":"2020-041A"},"OBJECT_NUMBER":{"0":"20452","1":"38833","2":"38833","3":"38833","4":"38833","5":"45854","6":"45854","7":"45854"},"SEMIMAJOR_AXIS":{"0":"27574.850","1":"26560.279","2":"26560.279","3":"26560.279","4":"26560.277","5":"26560.097","6":"26560.093","7":"26560.093"},"PERIOD":{"0":"759.503","1":"717.974","2":"717.974","3":"717.974","4":"717.974","5":"717.967","6":"717.966","7":"717.966"},"APOGEE":{"0":"21235.298","1":"20542.427","2":"20542.427","3":"20542.435","4":"20542.467","5":"20262.354","6":"20262.334","7":"20262.334"},"PERIGEE":{"0":"21158.133","1":"19821.862","2":"19821.862","3":"19821.854","4":"19821.817","5":"20101.570","6":"20101.582","7":"20101.582"},"DECAYED":{"0":"0","1":"0","2":"0","3":"0","4":"0","5":"0","6":"0","7":"0"},"Fetch_Timestamp":{"0":"2025-06-12T20:52:43.524","1":"2025-06-12T20:52:43.524","2":"2025-06-12T20:52:43.524","3":"2025-06-12T20:52:43.524","4":"2025-06-12T20:52:43.524","5":"2025-06-12T20:52:43.524","6":"2025-06-12T20:52:43.524","7":"2025-06-12T20:52:43.524"}}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import jax.numpy as jnp
|
|
2
2
|
from jax import jit, vmap, jacrev, config, Array
|
|
3
3
|
from tabsim.jax.utils import jit_with_doc
|
|
4
|
+
from jax.lax import scan
|
|
4
5
|
|
|
5
6
|
config.update("jax_enable_x64", True)
|
|
6
7
|
|
|
@@ -690,7 +691,7 @@ def calculate_fringe_frequency(
|
|
|
690
691
|
r_ecef = xyz_to_itrf(rfi_xyz, gsa)
|
|
691
692
|
s_ecef = r_ecef - jnp.mean(ants_itrf, axis=0)
|
|
692
693
|
s_hat_ecef = s_ecef / jnp.linalg.norm(s_ecef, axis=-1, keepdims=True)
|
|
693
|
-
s_hat_dot = jnp.gradient(s_hat_ecef, times, axis=0)
|
|
694
|
+
s_hat_dot = jnp.gradient(s_hat_ecef, jnp.diff(times[:2])[0], axis=0)
|
|
694
695
|
|
|
695
696
|
a1, a2 = jnp.triu_indices(len(ants_itrf), 1)
|
|
696
697
|
bl_ecef = ants_itrf[a1] - ants_itrf[a2]
|
|
@@ -1080,3 +1081,256 @@ def orbit_fisher(times: Array, orbit_params: Array, RIC_std: Array) -> Array:
|
|
|
1080
1081
|
fisher = vmap(propagate, in_axes=(0, None))(J, F).sum(axis=0)
|
|
1081
1082
|
|
|
1082
1083
|
return fisher
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
# New Orbit Model with Keplerian Elements
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
def R_z(angle):
|
|
1090
|
+
c, s = jnp.cos(angle), jnp.sin(angle)
|
|
1091
|
+
return jnp.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
def R_x(angle):
|
|
1095
|
+
c, s = jnp.cos(angle), jnp.sin(angle)
|
|
1096
|
+
return jnp.array([[1, 0, 0], [0, c, -s], [0, s, c]])
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
def solve_kepler(M, e, max_iter=100):
|
|
1100
|
+
"""Newton-Raphson solver for Kepler's equation."""
|
|
1101
|
+
|
|
1102
|
+
def newton_step(E, _):
|
|
1103
|
+
f = E - e * jnp.sin(E) - M
|
|
1104
|
+
f_prime = 1 - e * jnp.cos(E)
|
|
1105
|
+
E_new = E - f / f_prime
|
|
1106
|
+
return E_new, E_new
|
|
1107
|
+
|
|
1108
|
+
E0 = M
|
|
1109
|
+
E_final, _ = scan(newton_step, E0, None, length=max_iter)
|
|
1110
|
+
|
|
1111
|
+
return E_final
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
def kepler_orbit(times, t_epoch, params):
|
|
1115
|
+
"""
|
|
1116
|
+
Compute orbit position over time for a single satellite.
|
|
1117
|
+
|
|
1118
|
+
times: (T,)
|
|
1119
|
+
params: (6,) = [a, e, i, Ω, ω, M0]
|
|
1120
|
+
Returns: (T, 3)
|
|
1121
|
+
"""
|
|
1122
|
+
a, e, i_deg, Ω_deg, ω_deg, M0_deg = params
|
|
1123
|
+
|
|
1124
|
+
mu = 398600.4418 # km^3/s^2
|
|
1125
|
+
|
|
1126
|
+
n = jnp.sqrt(mu / jnp.abs(a) ** 3) * 86400
|
|
1127
|
+
|
|
1128
|
+
i = jnp.radians(i_deg)
|
|
1129
|
+
Ω = jnp.radians(Ω_deg)
|
|
1130
|
+
ω = jnp.radians(ω_deg)
|
|
1131
|
+
M_0 = jnp.radians(M0_deg)
|
|
1132
|
+
|
|
1133
|
+
M = M_0 + n * (times - t_epoch) # Mean anomaly
|
|
1134
|
+
|
|
1135
|
+
E = vmap(solve_kepler, (0, None))(jnp.atleast_1d(M), e)
|
|
1136
|
+
|
|
1137
|
+
nu = 2 * jnp.arctan2(
|
|
1138
|
+
jnp.sqrt(1 + e) * jnp.sin(E / 2), jnp.sqrt(1 - e) * jnp.cos(E / 2)
|
|
1139
|
+
)
|
|
1140
|
+
|
|
1141
|
+
r = a * (1 - e * jnp.cos(E))
|
|
1142
|
+
x_orb = r * jnp.cos(nu)
|
|
1143
|
+
y_orb = r * jnp.sin(nu)
|
|
1144
|
+
z_orb = jnp.zeros_like(x_orb)
|
|
1145
|
+
|
|
1146
|
+
R = R_z(Ω) @ R_x(i) @ R_z(ω)
|
|
1147
|
+
|
|
1148
|
+
pos_orb = jnp.stack([x_orb, y_orb, z_orb], axis=1) # (T, 3)
|
|
1149
|
+
pos_inertial = pos_orb @ R.T # (T, 3)
|
|
1150
|
+
|
|
1151
|
+
return pos_inertial * 1e3
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
def kepler_orbit_many(
|
|
1155
|
+
times_jd: Array,
|
|
1156
|
+
epoch_jd: Array,
|
|
1157
|
+
elements: Array,
|
|
1158
|
+
# semi_major: Array,
|
|
1159
|
+
# eccentricity: Array,
|
|
1160
|
+
# inclination: Array,
|
|
1161
|
+
# ra_of_asc_node: Array,
|
|
1162
|
+
# arg_of_peri: Array,
|
|
1163
|
+
# mean_anomaly: Array,
|
|
1164
|
+
):
|
|
1165
|
+
"""Propagate Keplerian orbits for a set of satellites using orbital elements as defined in a TLE.
|
|
1166
|
+
|
|
1167
|
+
Parameters
|
|
1168
|
+
----------
|
|
1169
|
+
times_jd : Array (n_time,)
|
|
1170
|
+
Propagation times in Julian Date.
|
|
1171
|
+
epoch_jd : Array (n_sat,)
|
|
1172
|
+
Epoch of the TLE in Julian Date.
|
|
1173
|
+
semi_major : Array (n_sat,)
|
|
1174
|
+
Semi major axis of the orbit in km.
|
|
1175
|
+
eccentricity : Array (n_sat,)
|
|
1176
|
+
Eccentricity of the orbit.
|
|
1177
|
+
inclination : Array (n_sat,)
|
|
1178
|
+
Inclination of the orbit in degrees.
|
|
1179
|
+
ra_of_asc_node : Array (n_sat,)
|
|
1180
|
+
Right ascension of the ascending node in degrees.
|
|
1181
|
+
arg_of_peri : Array (n_sat,)
|
|
1182
|
+
Argument of the pericentre in degrees.
|
|
1183
|
+
mean_anomaly : Array (n_sat,)
|
|
1184
|
+
Mean anomaly of the orbit at the epoch time in degrees.
|
|
1185
|
+
"""
|
|
1186
|
+
|
|
1187
|
+
# elements = [
|
|
1188
|
+
# jnp.atleast_1d(x)
|
|
1189
|
+
# for x in [
|
|
1190
|
+
# semi_major,
|
|
1191
|
+
# eccentricity,
|
|
1192
|
+
# inclination,
|
|
1193
|
+
# ra_of_asc_node,
|
|
1194
|
+
# arg_of_peri,
|
|
1195
|
+
# mean_anomaly,
|
|
1196
|
+
# ]
|
|
1197
|
+
# ]
|
|
1198
|
+
|
|
1199
|
+
pos = vmap(kepler_orbit, (None, 0, 0))(times_jd, epoch_jd, elements)
|
|
1200
|
+
|
|
1201
|
+
return pos
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
def kepler_orbit_velocity(times_jd: Array, epoch_jd: float, elements: Array) -> Array:
|
|
1205
|
+
|
|
1206
|
+
vel_vmap = vmap(jacrev(kepler_orbit, argnums=(0)), in_axes=(0, None, None))
|
|
1207
|
+
velocity = vel_vmap(times_jd, epoch_jd, elements).reshape(len(times_jd), 3)
|
|
1208
|
+
|
|
1209
|
+
return velocity
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
def R_uvw(
|
|
1213
|
+
times_jd: Array,
|
|
1214
|
+
epoch_jd: float,
|
|
1215
|
+
elements: Array,
|
|
1216
|
+
) -> Array:
|
|
1217
|
+
"""
|
|
1218
|
+
Calculate the rotation matrices at each time step to transform from an Earth
|
|
1219
|
+
centric reference frame (ECI) to a satellite centric frame given the
|
|
1220
|
+
parameters of its (circular) orbit.
|
|
1221
|
+
|
|
1222
|
+
Parameters
|
|
1223
|
+
----------
|
|
1224
|
+
times: ndarray (n_time,)
|
|
1225
|
+
Times at which to evaluate the rotation matrices.
|
|
1226
|
+
elevation: float
|
|
1227
|
+
Elevation/Altitude of the orbit in metres.
|
|
1228
|
+
inclination: float
|
|
1229
|
+
Inclination angle of the orbit relative to the equatorial plane.
|
|
1230
|
+
lon_asc_node: float
|
|
1231
|
+
Longitude of the ascending node of the orbit. This is the longitude of
|
|
1232
|
+
when the orbit crosses the equator from the south to the north.
|
|
1233
|
+
periapsis: float
|
|
1234
|
+
Perisapsis of the orbit. This is the angular starting point of the orbit
|
|
1235
|
+
at t = 0.
|
|
1236
|
+
|
|
1237
|
+
Returns
|
|
1238
|
+
-------
|
|
1239
|
+
R: ndarray (3, 3)
|
|
1240
|
+
The rotation matrix to orient to a satellite centric (RIC) frame defined
|
|
1241
|
+
by the Radial, In-track, Cross-track components.
|
|
1242
|
+
"""
|
|
1243
|
+
times_jd = jnp.asarray(times_jd)
|
|
1244
|
+
elements = jnp.asarray(elements)
|
|
1245
|
+
|
|
1246
|
+
position = kepler_orbit(times_jd, epoch_jd, elements)
|
|
1247
|
+
velocity = kepler_orbit_velocity(times_jd, epoch_jd, elements)
|
|
1248
|
+
|
|
1249
|
+
vel_hat = velocity / jnp.linalg.norm(velocity, axis=-1, keepdims=True)
|
|
1250
|
+
u_hat = position / jnp.linalg.norm(position, axis=-1, keepdims=True)
|
|
1251
|
+
w_hat = jnp.cross(u_hat, vel_hat)
|
|
1252
|
+
v_hat = jnp.cross(w_hat, u_hat)
|
|
1253
|
+
R = jnp.stack([u_hat.T, v_hat.T, w_hat.T])
|
|
1254
|
+
|
|
1255
|
+
return R
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
def kepler_RIC_dev(
|
|
1259
|
+
times_jd: Array,
|
|
1260
|
+
epoch_jd: float,
|
|
1261
|
+
true_elements: Array,
|
|
1262
|
+
estimated_elements: Array,
|
|
1263
|
+
) -> Array:
|
|
1264
|
+
"""
|
|
1265
|
+
Calculate the Radial (R), In-track (I) and Cross-track (C) deviations
|
|
1266
|
+
between two circular orbits given their orbit parameters at many time steps.
|
|
1267
|
+
|
|
1268
|
+
Parameters
|
|
1269
|
+
----------
|
|
1270
|
+
times: array (n_time,)
|
|
1271
|
+
Times at which to evaluate the RIC deviations.
|
|
1272
|
+
true_orb_params: ndarray (4,)
|
|
1273
|
+
Orbit parameters (elevation, inclination, lon_asc_node, periapsis) of
|
|
1274
|
+
the object of most interest. The more accurate measurement when
|
|
1275
|
+
comparing the same object.
|
|
1276
|
+
est_orb_params: array (elevation, inclination, lon_asc_node, periapsis)
|
|
1277
|
+
Estimated orbit parameters.
|
|
1278
|
+
|
|
1279
|
+
Returns
|
|
1280
|
+
-------
|
|
1281
|
+
RIC: ndarray (n_time, 3)
|
|
1282
|
+
Radial, In-track and Cross-track coordinates, in metres, of the orbiting
|
|
1283
|
+
body relative to the orbit defined by 'true_orbit_params'.
|
|
1284
|
+
"""
|
|
1285
|
+
times_jd = jnp.asarray(times_jd)
|
|
1286
|
+
true_elements = jnp.asarray(true_elements)
|
|
1287
|
+
estimated_elements = jnp.asarray(estimated_elements)
|
|
1288
|
+
|
|
1289
|
+
true_xyz = kepler_orbit(times_jd, epoch_jd, true_elements)
|
|
1290
|
+
est_xyz = kepler_orbit(times_jd, epoch_jd, estimated_elements)
|
|
1291
|
+
|
|
1292
|
+
R = R_uvw(times_jd, epoch_jd, true_elements)
|
|
1293
|
+
true_uvw = vmap(lambda x, y: x @ y, in_axes=(-1, 0))(R, true_xyz)
|
|
1294
|
+
est_uvw = vmap(lambda x, y: x @ y, in_axes=(-1, 0))(R, est_xyz)
|
|
1295
|
+
|
|
1296
|
+
return est_uvw - true_uvw
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
def kepler_orbit_fisher(
|
|
1300
|
+
times_jd: Array, epoch_jd: float, elements: Array, RIC_std: Array
|
|
1301
|
+
) -> Array:
|
|
1302
|
+
"""
|
|
1303
|
+
Calculate the inverse covariance (Fisher) matrix in orbital elements
|
|
1304
|
+
induced by errors in the RIC frame of an orbiting object. This is
|
|
1305
|
+
essentially linear uncertainty propagation assuming Gaussian errors.
|
|
1306
|
+
|
|
1307
|
+
Parameters
|
|
1308
|
+
----------
|
|
1309
|
+
times: ndarray (n_time,)
|
|
1310
|
+
Times at which the RIC covariance/standard deviations is defined.
|
|
1311
|
+
orbit_params: ndarray (4,)
|
|
1312
|
+
Orbit parameters (elevation, inclination, lon_asc_node, periapsis) for
|
|
1313
|
+
the orbit defining the origin of the RIC frame.
|
|
1314
|
+
RIC_std: ndarray (3,)
|
|
1315
|
+
The standard deviation in the Radial, In-track and Cross-track
|
|
1316
|
+
directions.
|
|
1317
|
+
|
|
1318
|
+
Returns
|
|
1319
|
+
-------
|
|
1320
|
+
fisher: ndarray (6, 6)
|
|
1321
|
+
The inverse covariance (Fisher) matrix for the orbit parameters induced
|
|
1322
|
+
by the orbit uncertainties in the RIC frame.
|
|
1323
|
+
"""
|
|
1324
|
+
times_jd = jnp.asarray(times_jd)
|
|
1325
|
+
elements = jnp.asarray(elements)
|
|
1326
|
+
RIC_std = jnp.asarray(RIC_std)
|
|
1327
|
+
|
|
1328
|
+
J = jacrev(kepler_RIC_dev, argnums=(3,))(times_jd, epoch_jd, elements, elements)[0]
|
|
1329
|
+
F = jnp.diag(1.0 / RIC_std**2)
|
|
1330
|
+
|
|
1331
|
+
def propagate(J, F):
|
|
1332
|
+
return J.T @ F @ J
|
|
1333
|
+
|
|
1334
|
+
fisher = vmap(propagate, in_axes=(0, None))(J, F).sum(axis=0)
|
|
1335
|
+
|
|
1336
|
+
return fisher
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import os
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
3
5
|
|
|
4
6
|
from tabsim.config import load_config, run_sim_config
|
|
5
7
|
|
|
8
|
+
from typing import Union
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
|
|
11
|
+
def get_abs_path(rel_path: Union[str, None], work_dir: str) -> Union[str, None]:
|
|
8
12
|
if rel_path:
|
|
9
13
|
return os.path.abspath(os.path.join(work_dir, rel_path))
|
|
10
14
|
else:
|
|
@@ -63,6 +67,11 @@ def main():
|
|
|
63
67
|
args = parser.parse_args()
|
|
64
68
|
rfi_amp = args.rfi_amp
|
|
65
69
|
spacetrack_path = args.spacetrack
|
|
70
|
+
config_path = Path(args.config_path)
|
|
71
|
+
|
|
72
|
+
if not config_path.is_file():
|
|
73
|
+
print(f"Error: config file not found: {config_path}", file=sys.stderr)
|
|
74
|
+
sys.exit(1) # Exit with error code
|
|
66
75
|
|
|
67
76
|
config_path = os.path.abspath(args.config_path)
|
|
68
77
|
work_dir = os.path.split(config_path)[0]
|
|
@@ -2,8 +2,10 @@ import numpy as np
|
|
|
2
2
|
import jax.numpy as jnp
|
|
3
3
|
import dask.array as da
|
|
4
4
|
|
|
5
|
+
from typing import Optional
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
def uniform_points_disk(radius: float, n_src: int, random_seed: Optional[int] = None):
|
|
7
9
|
"""
|
|
8
10
|
Generate uniformly distributed random points on a disk.
|
|
9
11
|
|
|
@@ -21,8 +21,10 @@ from glob import glob
|
|
|
21
21
|
|
|
22
22
|
from importlib.resources import files
|
|
23
23
|
|
|
24
|
+
from typing import Optional
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
|
|
27
|
+
def make_tle_dir(tle_dir: Optional[str]):
|
|
26
28
|
|
|
27
29
|
if tle_dir:
|
|
28
30
|
tle_dir = os.path.abspath(tle_dir)
|
|
@@ -89,7 +91,7 @@ def get_tles_by_id(
|
|
|
89
91
|
epoch_jd: float,
|
|
90
92
|
window_days: float = 1.0,
|
|
91
93
|
limit: int = 2000,
|
|
92
|
-
tle_dir: str
|
|
94
|
+
tle_dir: Optional[str] = None,
|
|
93
95
|
) -> pd.DataFrame:
|
|
94
96
|
|
|
95
97
|
tle_dir = make_tle_dir(tle_dir)
|
|
@@ -166,7 +168,7 @@ def get_tles_by_name(
|
|
|
166
168
|
epoch_jd: float,
|
|
167
169
|
window_days: float = 1.0,
|
|
168
170
|
limit: int = 10000,
|
|
169
|
-
tle_dir: str
|
|
171
|
+
tle_dir: Optional[str] = None,
|
|
170
172
|
) -> pd.DataFrame:
|
|
171
173
|
|
|
172
174
|
tle_dir = make_tle_dir(tle_dir)
|
|
@@ -291,7 +293,7 @@ def get_visible_satellite_tles(
|
|
|
291
293
|
min_elevation: float,
|
|
292
294
|
names: ArrayLike = [],
|
|
293
295
|
norad_ids: ArrayLike = [],
|
|
294
|
-
tle_dir: str
|
|
296
|
+
tle_dir: Optional[str] = None,
|
|
295
297
|
) -> tuple:
|
|
296
298
|
"""Get the TLEs corresponding to satellites that satisfy the conditions given.
|
|
297
299
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
4
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from tabsim.dask.observation import Observation
|
|
@@ -12,9 +12,11 @@ import dask
|
|
|
12
12
|
import dask.array as da
|
|
13
13
|
import numpy as np
|
|
14
14
|
import xarray as xr
|
|
15
|
-
from daskms import Dataset, xds_to_table
|
|
15
|
+
from daskms import Dataset, xds_to_table, xds_from_ms
|
|
16
16
|
import numpy as np
|
|
17
17
|
|
|
18
|
+
from dask.array.core import Array
|
|
19
|
+
|
|
18
20
|
|
|
19
21
|
def rm_dir(path: str, overwrite: bool = True):
|
|
20
22
|
"""Remove a directory but check for existence and overwrite flag before.
|
|
@@ -73,7 +75,7 @@ def mk_obs_dir(output_path: str, obs_name: str, overwrite: bool = True) -> tuple
|
|
|
73
75
|
return save_path, zarr_path, ms_path
|
|
74
76
|
|
|
75
77
|
|
|
76
|
-
def mk_obs_name(prefix: str, obs: Observation, suffix: str = None) -> str:
|
|
78
|
+
def mk_obs_name(prefix: str, obs: Observation, suffix: Optional[str] = None) -> str:
|
|
77
79
|
"""Construct an observation name based on the parameters of the observation and an additional prefix.
|
|
78
80
|
|
|
79
81
|
Parameters
|
|
@@ -381,6 +383,40 @@ def get_stationary_rfi_data(obs: Observation):
|
|
|
381
383
|
return rfi_stat
|
|
382
384
|
|
|
383
385
|
|
|
386
|
+
def add_to_ms(ds: Dataset, ms_path: str, flags: Optional[Array] = None):
|
|
387
|
+
|
|
388
|
+
n_time = ds.attrs["n_time"]
|
|
389
|
+
n_freq = ds.attrs["n_freq"]
|
|
390
|
+
n_corr = 1
|
|
391
|
+
n_bl = ds.attrs["n_bl"]
|
|
392
|
+
n_row = n_time * n_bl
|
|
393
|
+
|
|
394
|
+
xds_ms = xds_from_ms(ms_path)[0]
|
|
395
|
+
|
|
396
|
+
dims = ["row", "chan", "corr"]
|
|
397
|
+
chunks = {k: v for k, v in xds_ms.chunks.items() if k in dims}
|
|
398
|
+
|
|
399
|
+
vis_rfi = ds.vis_rfi.data.reshape(n_row, n_freq, n_corr)
|
|
400
|
+
vis_rfi = xr.DataArray(
|
|
401
|
+
da.stack(
|
|
402
|
+
[vis_rfi, da.zeros_like(vis_rfi), da.zeros_like(vis_rfi), vis_rfi], axis=2
|
|
403
|
+
),
|
|
404
|
+
dims=("row", "chan", "corr"),
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
xds_ms = xds_ms.assign(DATA=xds_ms.DATA + vis_rfi)
|
|
408
|
+
cols = "DATA"
|
|
409
|
+
|
|
410
|
+
if flags:
|
|
411
|
+
flags = xr.DataArray(
|
|
412
|
+
ds.flags.data.reshape(n_row, n_freq, n_corr), dims=("row", "chan", "corr")
|
|
413
|
+
)
|
|
414
|
+
xds_ms = xds_ms.assign(FLAG=flags)
|
|
415
|
+
cols.append("FLAG")
|
|
416
|
+
|
|
417
|
+
dask.compute(xds_to_table([xds_ms], ms_path, cols))
|
|
418
|
+
|
|
419
|
+
|
|
384
420
|
def write_ms(
|
|
385
421
|
ds: Dataset,
|
|
386
422
|
ms_path: str,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tabsim
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Trajectory-based Radio Frequency Interference (RFI) simulations for radio interferometeric data.
|
|
5
5
|
Author-email: Chris Finlay <christopher.finlay@epfl.ch>
|
|
6
6
|
Maintainer-email: Chris Finlay <christopher.finlay@epfl.ch>
|
|
@@ -702,12 +702,18 @@ Requires-Dist: regions; extra == "sat"
|
|
|
702
702
|
Provides-Extra: ipy
|
|
703
703
|
Requires-Dist: ipython; extra == "ipy"
|
|
704
704
|
Requires-Dist: ipykernel; extra == "ipy"
|
|
705
|
+
Provides-Extra: test
|
|
706
|
+
Requires-Dist: pytest; extra == "test"
|
|
707
|
+
Provides-Extra: docs
|
|
708
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
709
|
+
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
705
710
|
Dynamic: license-file
|
|
706
711
|
|
|
707
712
|
# tab-sim
|
|
708
713
|
|
|
709
714
|
[](https://doi.org/10.1093/mnras/stad1979)
|
|
710
715
|
[](https://doi.org/10.48550/arXiv.2502.00106)
|
|
716
|
+
[](https://tab-sim.readthedocs.io/en/latest/?badge=latest)
|
|
711
717
|
|
|
712
718
|
**T**r**A**jectory **B**ased RFI **Sim**ulations of radio interferometry data.
|
|
713
719
|
A source to visibility model for RFI sources including certain near-field effects.
|
|
@@ -715,6 +721,10 @@ A source to visibility model for RFI sources including certain near-field effect
|
|
|
715
721
|
`tab-sim` is written in [JAX](https://jax.readthedocs.io/en/latest/notebooks/quickstart.html)
|
|
716
722
|
and [Dask](https://www.dask.org) and can therefore use GPUs and/or CPUs to perform larger than memory computation.
|
|
717
723
|
|
|
724
|
+
## Documentation
|
|
725
|
+
|
|
726
|
+
[https://tab-sim.readthedocs.io/](https://tab-sim.readthedocs.io/)
|
|
727
|
+
|
|
718
728
|
## Installation
|
|
719
729
|
|
|
720
730
|
The following instructions are expected to work on Linux machine. If you are running Windows it is recommended to use WSL. If you are running Mac then it is best to start with a [conda](https://docs.conda.io/en/latest/)/[mamba](https://mamba.readthedocs.io/en/latest/index.html) environment and install `python-casacore` before continuing with the `pip` install method. If all else fails there is the [Docker install](#docker).
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
|
+
docs/conf.py
|
|
4
5
|
tabsim/__init__.py
|
|
5
6
|
tabsim/config.py
|
|
6
7
|
tabsim/plot.py
|
|
@@ -29,6 +30,7 @@ tabsim/data/aux_data/satellite.ole
|
|
|
29
30
|
tabsim/data/aux_data/satellite.rfimodel
|
|
30
31
|
tabsim/data/aux_data/stationary.loc
|
|
31
32
|
tabsim/data/aux_data/stationary.rfimodel
|
|
33
|
+
tabsim/data/aux_data/tles/2023-02-21-J8HE0T.json
|
|
32
34
|
tabsim/data/config_files/sim_config_base.yaml
|
|
33
35
|
tabsim/data/config_files/tab_config_base.yaml
|
|
34
36
|
tabsim/jax/__init__.py
|
|
@@ -39,4 +41,7 @@ tabsim/scripts/__init__.py
|
|
|
39
41
|
tabsim/scripts/ast_region.py
|
|
40
42
|
tabsim/scripts/flag_data.py
|
|
41
43
|
tabsim/scripts/sim_vis.py
|
|
42
|
-
tabsim/scripts/tle_sat_region.py
|
|
44
|
+
tabsim/scripts/tle_sat_region.py
|
|
45
|
+
tests/test_basic.py
|
|
46
|
+
tests/test_sim-vis.py
|
|
47
|
+
tests/test_version.py
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import pytest
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from tabsim.scripts import sim_vis
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_sim_vis_help_exists(capsys):
|
|
9
|
+
test_args = ["sim-vis", "--help"]
|
|
10
|
+
|
|
11
|
+
with patch.object(sys, "argv", test_args):
|
|
12
|
+
with pytest.raises(SystemExit) as e:
|
|
13
|
+
sim_vis.main()
|
|
14
|
+
|
|
15
|
+
assert e.value.code == 0 # argparse exits with code 0 for --help
|
|
16
|
+
out = capsys.readouterr().out
|
|
17
|
+
assert "usage:" in out.lower()
|
|
18
|
+
assert "--help" in out
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_missing_config_file():
|
|
22
|
+
args = ["sim-vis", "--config", "nonexistent.yaml"]
|
|
23
|
+
|
|
24
|
+
with patch.object(sys, "argv", args), pytest.raises(SystemExit):
|
|
25
|
+
sim_vis.main()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_simulation_runs_with_config(capsys):
|
|
29
|
+
config_path = (
|
|
30
|
+
Path(__file__).parent.parent / "examples" / "test" / "sim_test_16A.yaml"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
assert config_path.is_file(), f"Missing config file: {config_path}"
|
|
34
|
+
args = ["sim-vis", "--config", str(config_path), "-o"]
|
|
35
|
+
|
|
36
|
+
with patch.object(sys, "argv", args):
|
|
37
|
+
sim_vis.main()
|
|
38
|
+
|
|
39
|
+
output = capsys.readouterr().out
|
|
40
|
+
assert "Total simulation time" in output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|