astrotrack 0.1.0__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.
- astrotrack-0.1.0/LICENSE +28 -0
- astrotrack-0.1.0/PKG-INFO +157 -0
- astrotrack-0.1.0/README.md +130 -0
- astrotrack-0.1.0/astrotrack/__init__.py +22 -0
- astrotrack-0.1.0/astrotrack/doppler_analysis.py +111 -0
- astrotrack-0.1.0/astrotrack/preprocess.py +319 -0
- astrotrack-0.1.0/astrotrack/psd_analysis.py +493 -0
- astrotrack-0.1.0/astrotrack/satcon_animate.py +171 -0
- astrotrack-0.1.0/astrotrack/satcon_properties.py +420 -0
- astrotrack-0.1.0/astrotrack.egg-info/PKG-INFO +157 -0
- astrotrack-0.1.0/astrotrack.egg-info/SOURCES.txt +14 -0
- astrotrack-0.1.0/astrotrack.egg-info/dependency_links.txt +1 -0
- astrotrack-0.1.0/astrotrack.egg-info/requires.txt +16 -0
- astrotrack-0.1.0/astrotrack.egg-info/top_level.txt +1 -0
- astrotrack-0.1.0/pyproject.toml +43 -0
- astrotrack-0.1.0/setup.cfg +4 -0
astrotrack-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Gabriella Mariam Zahra Rajpoot
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: astrotrack
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A tool for analysing and investigating LEO satellite flyover occurrences with contamination in radio astronomy observational data.
|
|
5
|
+
Author-email: Gabriella Mariam Zahra Rajpoot <LetterToGabi@gmail.com>
|
|
6
|
+
License: BSD 3-Clause License
|
|
7
|
+
Keywords: astronomy,satellite,radio,signal,analysis,LEO,skyfield
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: numpy>=1.25
|
|
12
|
+
Requires-Dist: matplotlib>=3.5
|
|
13
|
+
Requires-Dist: pandas>=2.0
|
|
14
|
+
Requires-Dist: scipy>=1.10
|
|
15
|
+
Requires-Dist: astropy>=7.0
|
|
16
|
+
Requires-Dist: skyfield>=1.50
|
|
17
|
+
Requires-Dist: h5py>=3.10
|
|
18
|
+
Requires-Dist: tabulate>=0.9
|
|
19
|
+
Requires-Dist: tqdm>=4.60
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest; extra == "dev"
|
|
22
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
23
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
24
|
+
Requires-Dist: twine>=6.0; extra == "dev"
|
|
25
|
+
Requires-Dist: black; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# astrotrack: Characterising LEO Satellite RFI in Wide-Field Radio Astronomy
|
|
29
|
+
|
|
30
|
+
 
|
|
31
|
+
|
|
32
|
+
## Overview
|
|
33
|
+
|
|
34
|
+
`astrotrack` is an open-source Python package for characterising potential Low Earth Orbit (LEO) satellite interference in wide-field radio astronomy observations. While interferometric arrays are able to spatially localise LEO satellite radiation, wide-beam radiometers like REACH (de Lera Acedo et al. 2022) integrate the total sky power into a frequency spectrum and therefore lack equivalent strategies for identifying satellite-generated contamination. To address this limitation, `astrotrack` provides tools for combining Two-Line Element (TLE) data with site-specific observational constraints to identify LEO satellite flyovers and investigate their potential association with radio frequency interference (RFI).
|
|
35
|
+
|
|
36
|
+
> **Accompanying Paper**: *'astrotrack: Characterising LEO Satellite Interference in Wide-Field Radio Astronomy'*, in preparation.
|
|
37
|
+
|
|
38
|
+
<br>
|
|
39
|
+
<div align="center">
|
|
40
|
+
<img src="docs/images/animated_satellites.gif" width="600">
|
|
41
|
+
<p><em>3-D trajectory animation generated by AstroTrack's <code>satcon_animate</code> module of Eutelsat OneWeb satellite flyovers at the REACH site in the Karoo radio reserve, South Africa on 15 June 2025.</em></p>
|
|
42
|
+
</div>
|
|
43
|
+
<br>
|
|
44
|
+
|
|
45
|
+
## Repository Structure
|
|
46
|
+
|
|
47
|
+
| Paths | Description |
|
|
48
|
+
| ----- | ------------|
|
|
49
|
+
| [`data/`](data/) | CSV horizon profiles, including a [baseline](data/horizon-profiles/baseline-horizon.csv) and [REACH radiometer](data/horizon-profiles/REACH-horizon.csv) horizon profile. Alongside this, the [TLE catalogue](data/TLE-catalogues/TLEs.txt) used in exemplar and experimental analyses is provided. |
|
|
50
|
+
| [`docs/`](docs/) | [Example usage](docs/examples/) of functionalities across `astrotrack` modules. |
|
|
51
|
+
| [`astrotrack/`](astrotrack/) | `astrotrack` Python package source code. |
|
|
52
|
+
| [`notebooks/astrotrack_demo/`](/notebooks/astrotrack_demo/) | [Demonstration notebook](notebooks/astrotrack_demo/01_astrotrack_demo.ipynb) showing example `astrotrack` workflow. |
|
|
53
|
+
| [`notebooks/astrotrack_results/`](notebooks/astrotrack_results/) | Notebooks documenting experimental results and analyses. |
|
|
54
|
+
| [`tests`](tests/) | Unit tests validating `astrotrack` functionalities and edge case performance.|
|
|
55
|
+
| [`environment.yml`](environment.yml) | Conda environment for `astrotrack` specifying required dependencies.|
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## Data Availability
|
|
59
|
+
|
|
60
|
+
Raw HDF5 files containing PSD observations used for comparison are proprietary to the REACH collaboration and are therefore not made publicly available. The publicly available 12,270 TLEs used in this work are provided in a [CSV file](data/TLE-catalogues/TLEs.txt) downloaded from [Space-Track](https://www.space-track.org) on 17:10:37 UTC 14 June 2025.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## `astrotrack` Installation
|
|
64
|
+
|
|
65
|
+
To install `astrotrack` from source, follow the instructions below:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
conda env create -f environment.yml
|
|
69
|
+
conda activate astrotrack
|
|
70
|
+
pip install -e .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The package can then be imported using:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
import astrotrack
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`astrotrack` is recommended to be used with the provided Conda [environment](environment.yml).
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## Quick Start
|
|
83
|
+
|
|
84
|
+
The below example demonstrates how to initialise `astrotrack` using a provided TLE catalogue along with user-defined observational constraints, the satellite constellation of interest, and a target date:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from datetime import datetime
|
|
88
|
+
from astrotrack.preprocess import load_satellite_data
|
|
89
|
+
|
|
90
|
+
data = load_satellite_data(
|
|
91
|
+
tle_file="LEO_TLE_file.txt",
|
|
92
|
+
target_date=datetime(2025, 1, 18, 12, 25, 8),
|
|
93
|
+
obs_len=3600,
|
|
94
|
+
traj_res=60,
|
|
95
|
+
obs_lat=51.5,
|
|
96
|
+
obs_lon=-0.1,
|
|
97
|
+
R=2000,
|
|
98
|
+
horizon_data="Horizon-Profile.csv",
|
|
99
|
+
satcon="STARLINK"
|
|
100
|
+
)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> **Generating Epoch Times with Skyfield**: The following code can be used to initialise a time array for satellite propagation.
|
|
104
|
+
>
|
|
105
|
+
>```python
|
|
106
|
+
>import numpy as np
|
|
107
|
+
>from skyfield.api import load
|
|
108
|
+
>
|
|
109
|
+
># Create a timescale object:
|
|
110
|
+
>ts = load.timescale()
|
|
111
|
+
>
|
|
112
|
+
># Define orbit duration:
|
|
113
|
+
>orbit_duration = np.arange(0, 3600, 1) # in seconds
|
|
114
|
+
>
|
|
115
|
+
># Generate time array:
|
|
116
|
+
>epochs_of_orbit = ts.utc(2025, 1, 1, 10, 15, 0 + orbit_duration)
|
|
117
|
+
>```
|
|
118
|
+
>
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
## Example Usage & Workflow
|
|
122
|
+
|
|
123
|
+
`astrotrack` is organised into five modules. A typical workflow begins with initialising and structuring satellite Two-Line Element (TLE) data for analysis, after which the subsequent modules derive orbital properties, Doppler behaviour with respect to a ground-based experiment, animations, and enable spectral associations.
|
|
124
|
+
|
|
125
|
+
<br>
|
|
126
|
+
<div align="center">
|
|
127
|
+
<img src="docs/images/package-modules.png" width="600">
|
|
128
|
+
</div>
|
|
129
|
+
<br>
|
|
130
|
+
|
|
131
|
+
- [`preprocess`](): Loads and filters satellite TLE data provided by the user.
|
|
132
|
+
- [`satcon_properties`](): Filters, analyses, and visualises satellite trajectories as well as their metrics.
|
|
133
|
+
- [`doppler_analysis`](): Evaluates Doppler shifts and detectability relative to a user-defined instrument's specifications.
|
|
134
|
+
- [`satcon_animate`](): Generates 3-D trajectory animations.
|
|
135
|
+
- [`psd_analysis`](): Visualises satellite flyover properties alongside measured PSD data coincidential with satellite flyovers.
|
|
136
|
+
|
|
137
|
+
A detailed overview of all five modules, their key functions, and example usage is provided in a supplementary [document](docs/examples/examples.md).
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
A [demonstration notebook](notebooks/astrotrack_demo/01_astrotrack_demo.ipynb) is also provided, and includes usage of an example [horizon profile](data/horizon-profiles/REACH-horizon.csv) from the REACH experiment as well as a [TLE catalogue](data/TLE-catalogues/TLEs.txt) compiled from [Space-Track](https://www.space-track.org). A [baseline horizon profile](data/horizon-profiles/baseline-horizon.csv) corresponding to an idealised flat horizon is additionally available to be used directly, or modified by the user to incorporate site-specific observational constraints.
|
|
141
|
+
|
|
142
|
+
## Testing \& Validation
|
|
143
|
+
|
|
144
|
+
`astrotrack` is validated using unit tests covering the package's functionalities from [TLE preprocessing](tests/preprocess_test.py), deriving [satellite properties](tests/satcon_properties_test.py), performing [Doppler Analysis](tests/doppler_analysis_test.py), and analysis with [PSD observations](tests/psd_analysis_test.py).
|
|
145
|
+
|
|
146
|
+
The entire test suite can be run using:
|
|
147
|
+
```bash
|
|
148
|
+
pytest
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
The `astrotrack` Python package source code is released under BSD 3-Clause License, with citation details provided in the [`CITATION.cff`](CITATION.cff) file.
|
|
154
|
+
|
|
155
|
+
## Bibliography
|
|
156
|
+
|
|
157
|
+
de Lera Acedo, E., de Villiers, D.I.L., Razavi-Ghods, N. et al. *The REACH radiometer for detecting the 21-cm hydrogen signal from redshift z ≈ 7.5–28*. Nat Astron 6, 984–998 (2022). https://doi.org/10.1038/s41550-022-01709-9
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# astrotrack: Characterising LEO Satellite RFI in Wide-Field Radio Astronomy
|
|
2
|
+
|
|
3
|
+
 
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`astrotrack` is an open-source Python package for characterising potential Low Earth Orbit (LEO) satellite interference in wide-field radio astronomy observations. While interferometric arrays are able to spatially localise LEO satellite radiation, wide-beam radiometers like REACH (de Lera Acedo et al. 2022) integrate the total sky power into a frequency spectrum and therefore lack equivalent strategies for identifying satellite-generated contamination. To address this limitation, `astrotrack` provides tools for combining Two-Line Element (TLE) data with site-specific observational constraints to identify LEO satellite flyovers and investigate their potential association with radio frequency interference (RFI).
|
|
8
|
+
|
|
9
|
+
> **Accompanying Paper**: *'astrotrack: Characterising LEO Satellite Interference in Wide-Field Radio Astronomy'*, in preparation.
|
|
10
|
+
|
|
11
|
+
<br>
|
|
12
|
+
<div align="center">
|
|
13
|
+
<img src="docs/images/animated_satellites.gif" width="600">
|
|
14
|
+
<p><em>3-D trajectory animation generated by AstroTrack's <code>satcon_animate</code> module of Eutelsat OneWeb satellite flyovers at the REACH site in the Karoo radio reserve, South Africa on 15 June 2025.</em></p>
|
|
15
|
+
</div>
|
|
16
|
+
<br>
|
|
17
|
+
|
|
18
|
+
## Repository Structure
|
|
19
|
+
|
|
20
|
+
| Paths | Description |
|
|
21
|
+
| ----- | ------------|
|
|
22
|
+
| [`data/`](data/) | CSV horizon profiles, including a [baseline](data/horizon-profiles/baseline-horizon.csv) and [REACH radiometer](data/horizon-profiles/REACH-horizon.csv) horizon profile. Alongside this, the [TLE catalogue](data/TLE-catalogues/TLEs.txt) used in exemplar and experimental analyses is provided. |
|
|
23
|
+
| [`docs/`](docs/) | [Example usage](docs/examples/) of functionalities across `astrotrack` modules. |
|
|
24
|
+
| [`astrotrack/`](astrotrack/) | `astrotrack` Python package source code. |
|
|
25
|
+
| [`notebooks/astrotrack_demo/`](/notebooks/astrotrack_demo/) | [Demonstration notebook](notebooks/astrotrack_demo/01_astrotrack_demo.ipynb) showing example `astrotrack` workflow. |
|
|
26
|
+
| [`notebooks/astrotrack_results/`](notebooks/astrotrack_results/) | Notebooks documenting experimental results and analyses. |
|
|
27
|
+
| [`tests`](tests/) | Unit tests validating `astrotrack` functionalities and edge case performance.|
|
|
28
|
+
| [`environment.yml`](environment.yml) | Conda environment for `astrotrack` specifying required dependencies.|
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Data Availability
|
|
32
|
+
|
|
33
|
+
Raw HDF5 files containing PSD observations used for comparison are proprietary to the REACH collaboration and are therefore not made publicly available. The publicly available 12,270 TLEs used in this work are provided in a [CSV file](data/TLE-catalogues/TLEs.txt) downloaded from [Space-Track](https://www.space-track.org) on 17:10:37 UTC 14 June 2025.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## `astrotrack` Installation
|
|
37
|
+
|
|
38
|
+
To install `astrotrack` from source, follow the instructions below:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
conda env create -f environment.yml
|
|
42
|
+
conda activate astrotrack
|
|
43
|
+
pip install -e .
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The package can then be imported using:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
import astrotrack
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`astrotrack` is recommended to be used with the provided Conda [environment](environment.yml).
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
The below example demonstrates how to initialise `astrotrack` using a provided TLE catalogue along with user-defined observational constraints, the satellite constellation of interest, and a target date:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from datetime import datetime
|
|
61
|
+
from astrotrack.preprocess import load_satellite_data
|
|
62
|
+
|
|
63
|
+
data = load_satellite_data(
|
|
64
|
+
tle_file="LEO_TLE_file.txt",
|
|
65
|
+
target_date=datetime(2025, 1, 18, 12, 25, 8),
|
|
66
|
+
obs_len=3600,
|
|
67
|
+
traj_res=60,
|
|
68
|
+
obs_lat=51.5,
|
|
69
|
+
obs_lon=-0.1,
|
|
70
|
+
R=2000,
|
|
71
|
+
horizon_data="Horizon-Profile.csv",
|
|
72
|
+
satcon="STARLINK"
|
|
73
|
+
)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
> **Generating Epoch Times with Skyfield**: The following code can be used to initialise a time array for satellite propagation.
|
|
77
|
+
>
|
|
78
|
+
>```python
|
|
79
|
+
>import numpy as np
|
|
80
|
+
>from skyfield.api import load
|
|
81
|
+
>
|
|
82
|
+
># Create a timescale object:
|
|
83
|
+
>ts = load.timescale()
|
|
84
|
+
>
|
|
85
|
+
># Define orbit duration:
|
|
86
|
+
>orbit_duration = np.arange(0, 3600, 1) # in seconds
|
|
87
|
+
>
|
|
88
|
+
># Generate time array:
|
|
89
|
+
>epochs_of_orbit = ts.utc(2025, 1, 1, 10, 15, 0 + orbit_duration)
|
|
90
|
+
>```
|
|
91
|
+
>
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
## Example Usage & Workflow
|
|
95
|
+
|
|
96
|
+
`astrotrack` is organised into five modules. A typical workflow begins with initialising and structuring satellite Two-Line Element (TLE) data for analysis, after which the subsequent modules derive orbital properties, Doppler behaviour with respect to a ground-based experiment, animations, and enable spectral associations.
|
|
97
|
+
|
|
98
|
+
<br>
|
|
99
|
+
<div align="center">
|
|
100
|
+
<img src="docs/images/package-modules.png" width="600">
|
|
101
|
+
</div>
|
|
102
|
+
<br>
|
|
103
|
+
|
|
104
|
+
- [`preprocess`](): Loads and filters satellite TLE data provided by the user.
|
|
105
|
+
- [`satcon_properties`](): Filters, analyses, and visualises satellite trajectories as well as their metrics.
|
|
106
|
+
- [`doppler_analysis`](): Evaluates Doppler shifts and detectability relative to a user-defined instrument's specifications.
|
|
107
|
+
- [`satcon_animate`](): Generates 3-D trajectory animations.
|
|
108
|
+
- [`psd_analysis`](): Visualises satellite flyover properties alongside measured PSD data coincidential with satellite flyovers.
|
|
109
|
+
|
|
110
|
+
A detailed overview of all five modules, their key functions, and example usage is provided in a supplementary [document](docs/examples/examples.md).
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
A [demonstration notebook](notebooks/astrotrack_demo/01_astrotrack_demo.ipynb) is also provided, and includes usage of an example [horizon profile](data/horizon-profiles/REACH-horizon.csv) from the REACH experiment as well as a [TLE catalogue](data/TLE-catalogues/TLEs.txt) compiled from [Space-Track](https://www.space-track.org). A [baseline horizon profile](data/horizon-profiles/baseline-horizon.csv) corresponding to an idealised flat horizon is additionally available to be used directly, or modified by the user to incorporate site-specific observational constraints.
|
|
114
|
+
|
|
115
|
+
## Testing \& Validation
|
|
116
|
+
|
|
117
|
+
`astrotrack` is validated using unit tests covering the package's functionalities from [TLE preprocessing](tests/preprocess_test.py), deriving [satellite properties](tests/satcon_properties_test.py), performing [Doppler Analysis](tests/doppler_analysis_test.py), and analysis with [PSD observations](tests/psd_analysis_test.py).
|
|
118
|
+
|
|
119
|
+
The entire test suite can be run using:
|
|
120
|
+
```bash
|
|
121
|
+
pytest
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
The `astrotrack` Python package source code is released under BSD 3-Clause License, with citation details provided in the [`CITATION.cff`](CITATION.cff) file.
|
|
127
|
+
|
|
128
|
+
## Bibliography
|
|
129
|
+
|
|
130
|
+
de Lera Acedo, E., de Villiers, D.I.L., Razavi-Ghods, N. et al. *The REACH radiometer for detecting the 21-cm hydrogen signal from redshift z ≈ 7.5–28*. Nat Astron 6, 984–998 (2022). https://doi.org/10.1038/s41550-022-01709-9
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from .doppler_analysis import ( # noqa: F401
|
|
2
|
+
check_doppler_resolution,
|
|
3
|
+
plot_doppler_shifts,
|
|
4
|
+
)
|
|
5
|
+
from .preprocess import load_satellite_data # noqa: F401
|
|
6
|
+
from .psd_analysis import ( # noqa: F401
|
|
7
|
+
load_hdf5,
|
|
8
|
+
plot_psd_satellite_time_series,
|
|
9
|
+
plot_psd_with_satellite_metric,
|
|
10
|
+
)
|
|
11
|
+
from .satcon_animate import animate_trajectories # noqa: F401
|
|
12
|
+
from .satcon_properties import ( # noqa: F401
|
|
13
|
+
filter_by_norads,
|
|
14
|
+
filter_by_time,
|
|
15
|
+
filter_custom,
|
|
16
|
+
filter_nth,
|
|
17
|
+
get_norads,
|
|
18
|
+
plot_flyover_histogram_by_norad,
|
|
19
|
+
plot_max_elevation_histogram,
|
|
20
|
+
plot_satellite_metric,
|
|
21
|
+
plot_satellite_trajectory,
|
|
22
|
+
)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from tabulate import tabulate
|
|
5
|
+
|
|
6
|
+
default_font = "Times New Roman"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def plot_doppler_shifts(
|
|
10
|
+
all_satellite_data,
|
|
11
|
+
f0,
|
|
12
|
+
font_family=default_font,
|
|
13
|
+
figsize=(8, 5),
|
|
14
|
+
marker_color="deeppink",
|
|
15
|
+
time_window=10,
|
|
16
|
+
):
|
|
17
|
+
"""
|
|
18
|
+
Plot the Doppler shifts for each satellite in separate subplots,
|
|
19
|
+
centered around visibility midpoint.
|
|
20
|
+
|
|
21
|
+
Parameters:
|
|
22
|
+
----------
|
|
23
|
+
all_satellite_data : list[dict]
|
|
24
|
+
Satellite data dictionaries.
|
|
25
|
+
f0 : float
|
|
26
|
+
Transmission frequency [Hz].
|
|
27
|
+
font_family : str
|
|
28
|
+
Font family for plot text.
|
|
29
|
+
figsize : tuple
|
|
30
|
+
Figure size for each subplot.
|
|
31
|
+
marker_color : str
|
|
32
|
+
Color of scatter plot markers.
|
|
33
|
+
time_window : float
|
|
34
|
+
Half-width of x-axis around visibility [min].
|
|
35
|
+
"""
|
|
36
|
+
c = 3.0e5 # speed of light in km/s
|
|
37
|
+
for satellite_data in all_satellite_data:
|
|
38
|
+
plt.rcParams["font.family"] = font_family
|
|
39
|
+
plt.figure(figsize=figsize)
|
|
40
|
+
|
|
41
|
+
epochs = satellite_data["Epochs"]
|
|
42
|
+
velocity_r = np.array(satellite_data["Velocities"]) # km/s
|
|
43
|
+
elevations = satellite_data["Elevations"]
|
|
44
|
+
tle_line_2 = satellite_data["TLE"][1]
|
|
45
|
+
norad_id = tle_line_2.split()[1]
|
|
46
|
+
theta_max = max(elevations)
|
|
47
|
+
epochs_np = np.array([np.datetime64(e) for e in epochs])
|
|
48
|
+
center_time = epochs_np[len(epochs_np) // 2]
|
|
49
|
+
relative_time = (epochs_np - center_time) / np.timedelta64(1, "m") # mins
|
|
50
|
+
doppler_shift = (velocity_r / c) * f0
|
|
51
|
+
|
|
52
|
+
plt.scatter(
|
|
53
|
+
relative_time,
|
|
54
|
+
doppler_shift / 1e3,
|
|
55
|
+
s=3,
|
|
56
|
+
color=marker_color,
|
|
57
|
+
label=rf"$\theta_{{max}} \approx {theta_max:.0f}^\circ$",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
print_time = (
|
|
61
|
+
center_time.astype("datetime64[s]").tolist().strftime("%Y-%m-%d %H:%M:%S")
|
|
62
|
+
)
|
|
63
|
+
plt.xlabel("Visibility Time (min)")
|
|
64
|
+
plt.ylabel("Doppler Shift (kHz)")
|
|
65
|
+
plt.title(f"NORAD {norad_id} Doppler Shift (Centered at {print_time}):")
|
|
66
|
+
plt.axhline(0, color="black", linestyle="--")
|
|
67
|
+
plt.xlim(-time_window, time_window)
|
|
68
|
+
plt.legend(loc="upper right", fontsize=10)
|
|
69
|
+
plt.grid(True)
|
|
70
|
+
plt.show()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def check_doppler_resolution(
|
|
74
|
+
all_satellite_data, f0_array, resolution=12_000, experiment="REACH", return_df=False
|
|
75
|
+
):
|
|
76
|
+
"""
|
|
77
|
+
Check if Doppler shift can be resolved,
|
|
78
|
+
given experiment's frequency resolution.
|
|
79
|
+
|
|
80
|
+
Parameters:
|
|
81
|
+
----------
|
|
82
|
+
all_satellite_data : list[dict]
|
|
83
|
+
Satellite data dictionaries.
|
|
84
|
+
f0_array : array
|
|
85
|
+
Frequencies to test [Hz].
|
|
86
|
+
resolution : float
|
|
87
|
+
Frequency resolution of experiment [Hz].
|
|
88
|
+
experiment_name : str
|
|
89
|
+
Name of experiment.
|
|
90
|
+
"""
|
|
91
|
+
c = 3.0e5 # speed of light in km/s
|
|
92
|
+
rows = []
|
|
93
|
+
|
|
94
|
+
for satellite_data in all_satellite_data:
|
|
95
|
+
norad_id = satellite_data["TLE"][1].split()[1]
|
|
96
|
+
velocity_r = np.array(satellite_data["Velocities"])
|
|
97
|
+
f_max_needed = (resolution * c) / (np.max(np.abs(velocity_r)) * 1e6)
|
|
98
|
+
|
|
99
|
+
row = {"Satellite NORAD ID": norad_id}
|
|
100
|
+
for f0 in f0_array:
|
|
101
|
+
max_doppler_khz = np.max(np.abs((velocity_r / c) * f0)) / 1e3
|
|
102
|
+
row[f"{f0/1e6:.1f} MHz"] = f"""{max_doppler_khz:.2f} kHz | {
|
|
103
|
+
'YES' if max_doppler_khz > resolution/1e3 else 'NO'
|
|
104
|
+
}"""
|
|
105
|
+
row[f"Freq. to Resolve ({experiment})"] = f"{f_max_needed:.0f} MHz"
|
|
106
|
+
rows.append(row)
|
|
107
|
+
|
|
108
|
+
df = pd.DataFrame(rows)
|
|
109
|
+
print(tabulate(df, headers="keys", tablefmt="grid", showindex=False))
|
|
110
|
+
if return_df:
|
|
111
|
+
return df
|