mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2026-07-25 04:18:53 +00:00
Add titles in some Python plots
This commit is contained in:
+104
-99
@@ -45,11 +45,11 @@ repeat them with the default value that applies to each tool.
|
||||
Any directory in `--file-prefix` is resolved relative to `--input-path` (an
|
||||
absolute `--file-prefix` path overrides it).
|
||||
|
||||
When `--conf` is provided to the generic tracking and acquisition plotters,
|
||||
a multi-signal configuration expands to every enabled signal. Pass
|
||||
When `--conf` is provided to the generic tracking and acquisition plotters, a
|
||||
multi-signal configuration expands to every enabled signal. Pass
|
||||
`--signal-type` to restrict plots to one signal. Single-file modes and
|
||||
signal-specific scripts still require or prefer one signal. Channel ranges
|
||||
are computed using GNSS-SDR's receiver order:
|
||||
signal-specific scripts still require or prefer one signal. Channel ranges are
|
||||
computed using GNSS-SDR's receiver order:
|
||||
`1C, 2S, L5, 1B, 5X, E6, 1G, 2G, B1, B3, 7X, J1, J5`.
|
||||
|
||||
- `-o`, `--fig-path`: directory where plots are saved. Defaults to a per-script
|
||||
@@ -92,25 +92,30 @@ Output PNGs (`_2D` and `_3D`):
|
||||
<fig-path>/<output-basename>_<system>_<signal>_ch_<channel>_<execution>_sat_<PRN>_3D.png
|
||||
```
|
||||
|
||||
| Option | Default | Description |
|
||||
| ---------------------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the acquisition `.mat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer acquisition dump prefixes and signal selectors. |
|
||||
Each figure title uses a readable signal name and PRN, for example
|
||||
`GPS L1 C/A PRN 3 (channel 0, execution 1)`.
|
||||
|
||||
| Option | Default | Description |
|
||||
| ---------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the acquisition `.mat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer acquisition dump prefixes and signal selectors. |
|
||||
| `--file-prefix` | `--conf` or `acquisition` | `Acquisition.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/acquisition` | Output directory for PNGs. |
|
||||
| `--output-basename`, `--output-prefix` | `--file-prefix` basename | Base name for the saved PNGs (directory and extension stripped). |
|
||||
| `--all-files` / `--single-file` | `--all-files` | Plot every matching dump, or a single dump chosen by the selectors below. |
|
||||
| `--positive-only` / `--include-negative` | `--positive-only` | Plot only positive acquisitions, or positive and negative. |
|
||||
| `--lite-view` / `--full-view` | `--lite-view` | Interpolated light grid, or the raw acquisition grid. |
|
||||
| `--sat` | `1` in single-file mode | Satellite PRN. Filters in all-files mode; selects the dump in single-file mode. |
|
||||
| `--channel` | `0` in single-file mode | Acquisition channel number. Filter / selector. |
|
||||
| `--execution` | `1` in single-file mode | Acquisition dump execution index. Filter / selector. |
|
||||
| `--signal-type CODE` | `--conf` or `1C` | GNSS-SDR signal code (see table below); case-insensitive. Filters in all-files mode; selects in single-file mode. |
|
||||
| `--samples-per-chip` | `3` | Samples per chip used by the light-grid interpolation. |
|
||||
| `--samples-per-code` | `25000` | Samples per code used for the 2D normalization. |
|
||||
| `--input-power` | `100.0` | Input power used for the 2D normalization. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| `-o`, `--fig-path` | `plots/acquisition` | Output directory for PNGs. |
|
||||
| `--output-basename`, `--output-prefix` | `--file-prefix` basename | Base name for the saved PNGs (directory and extension stripped). |
|
||||
| `--all-files` / `--single-file` | `--all-files` | Plot every matching dump, or a single dump chosen by the selectors below. |
|
||||
| `--positive-only` / `--include-negative` | `--positive-only` | Plot only positive acquisitions, or positive and negative. |
|
||||
| `--lite-view` / `--full-view` | `--lite-view` | Interpolated light grid, or the raw acquisition grid. |
|
||||
| `--sat` | `1` in single-file mode | Satellite PRN. Filters in all-files mode; selects the dump in single-file mode. |
|
||||
| `--channel` | `0` in single-file mode | Acquisition channel number. Filter / selector. |
|
||||
| `--execution` | `1` in single-file mode | Acquisition dump execution index. Filter / selector. |
|
||||
| `--signal-type CODE` | `--conf` or `1C` | GNSS-SDR signal code (see table below); case-insensitive. Filters in all-files mode; selects in single-file mode. |
|
||||
| `--samples-per-chip` | `3` | Samples per chip used by the light-grid interpolation. |
|
||||
| `--samples-per-doppler-step` | `5` | Interpolated samples per Doppler step used by the light-grid interpolation. |
|
||||
| `--surface-smoothing` | `2.0` | Gaussian smoothing sigma for the lite 3D surface; use `0` to disable. |
|
||||
| `--samples-per-code` | `25000` | Samples per code used for the 2D normalization. |
|
||||
| `--input-power` | `100.0` | Input power used for the 2D normalization. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
|
||||
Signal codes accepted by `--signal-type`, using the same nomenclature as the
|
||||
GNSS-SDR configuration and dump filenames (e.g. `--signal-type=E6`):
|
||||
@@ -145,7 +150,7 @@ python3 plot_acq_grid.py --input-path ./out --fig-path ./plots/acquisition
|
||||
python3 plot_acq_grid.py --file-prefix hackrf_l1_acq_dump --channel 0
|
||||
python3 plot_acq_grid.py --file-prefix hackrf_l1_acq_dump --sat 26
|
||||
python3 plot_acq_grid.py --signal-type E6
|
||||
python3 plot_acq_grid.py --conf conf/File_input/Beidou/gnss-sdr_BDS_B3I_byte.conf --signal-type B3 --input-path ./out
|
||||
python3 plot_acq_grid.py --conf gnss-sdr_BDS_B3I_byte.conf
|
||||
python3 plot_acq_grid.py --single-file --signal-type J1 --sat 193 --channel 0 --execution 1
|
||||
python3 plot_acq_grid.py --single-file --sat 3 --channel 0 --execution 1 --full-view
|
||||
python3 plot_acq_grid.py --include-negative --output-basename my_run
|
||||
@@ -158,20 +163,20 @@ Reads per-channel tracking `.dat` dumps and plots VEML tracking diagnostics
|
||||
|
||||
Input pattern: `<input-path>/<file-prefix><channel>.dat`.
|
||||
|
||||
| Option | Default | Description |
|
||||
| ---------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the tracking `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer tracking dump prefix, sampling frequency, and channel range. |
|
||||
| `--file-prefix` | `--conf` or `track_ch` | `Tracking.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/dll-pll-veml-tracking` | Output directory for PNGs. |
|
||||
| `--sampling-frequency` | `--conf` or `3000000.0` | Signal sampling frequency in Hz (sets the RX-time axis). |
|
||||
| `--channels` | `--conf` or `5` | Number of channels to read. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| Option | Default | Description |
|
||||
| ---------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the tracking `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer tracking dump prefix, sampling frequency, and channel range. |
|
||||
| `--file-prefix` | `--conf` or `track_ch` | `Tracking.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/dll-pll-veml-tracking` | Output directory for PNGs. |
|
||||
| `--sampling-frequency` | `--conf` or `3000000.0` | Signal sampling frequency in Hz (sets the RX-time axis). |
|
||||
| `--channels` | `--conf` or `5` | Number of channels to read. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| `--signal-type CODE` | inferred if needed | GNSS-SDR signal code used to restrict channel ranges and dump filenames from `--conf`; omitted means all configured signals. |
|
||||
| `--plot-last-outputs` | `0` | Only plot the last N outputs; `0` plots all of them. |
|
||||
| `--no-doppler` | Doppler plots on | Skip the extra Doppler-only plots. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| `--plot-last-outputs` | `0` | Only plot the last N outputs; `0` plots all of them. |
|
||||
| `--no-doppler` | Doppler plots on | Skip the extra Doppler-only plots. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -189,19 +194,19 @@ Reads per-channel Kalman-filter tracking `.dat` dumps produced by the
|
||||
|
||||
Input pattern: `<input-path>/<file-prefix><channel>.dat`.
|
||||
|
||||
| Option | Default | Description |
|
||||
| ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the tracking `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer tracking dump prefix, sampling frequency, and channel range. |
|
||||
| `--file-prefix` | `--conf` or `track_ch` | `Tracking.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/kf-tracking` | Output directory for PNGs. |
|
||||
| `--sampling-frequency` | `--conf` or `4000000.0` | Signal sampling frequency in Hz. |
|
||||
| `--channels` | `--conf` or `5` | Number of channels to read. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| `--signal-type CODE` | inferred if needed | GNSS-SDR signal code used to select channel ranges and dump filenames from `--conf`. |
|
||||
| `--code-period` | `0.001` | Code period in seconds. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| Option | Default | Description |
|
||||
| ---------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the tracking `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer tracking dump prefix, sampling frequency, and channel range. |
|
||||
| `--file-prefix` | `--conf` or `track_ch` | `Tracking.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/kf-tracking` | Output directory for PNGs. |
|
||||
| `--sampling-frequency` | `--conf` or `4000000.0` | Signal sampling frequency in Hz. |
|
||||
| `--channels` | `--conf` or `5` | Number of channels to read. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| `--signal-type CODE` | inferred if needed | GNSS-SDR signal code used to select channel ranges and dump filenames from `--conf`. |
|
||||
| `--code-period` | `0.001` | Code period in seconds. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
|
||||
> The dumps must come from the `GPS_L1_CA_KF_Tracking` block; standard DLL/PLL
|
||||
> tracking dumps have a different record layout and will be misread.
|
||||
@@ -222,22 +227,22 @@ figures.
|
||||
|
||||
Input pattern: `<input-path>/<file-prefix><channel>.dat`.
|
||||
|
||||
| Option | Default | Description |
|
||||
| -------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the tracking `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer tracking dump prefix, sampling frequency, signal type, and channel range. |
|
||||
| `--file-prefix` | `--conf` or `track_ch` | `Tracking.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/tracking-quality` | Output directory for PNGs. |
|
||||
| `--sampling-frequency` | `--conf` or `4000000.0` | Signal sampling frequency in Hz. |
|
||||
| `--channels` | `--conf` or `5` | Number of channels to read. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| `--signal-type` | `--conf` or `1C` | GNSS-SDR signal code used to restrict channel ranges and label traces; omitted with multi-signal `--conf` means all configured signals. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| Option | Default | Description |
|
||||
| ---------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the tracking `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer tracking dump prefix, sampling frequency, signal type, and channel range. |
|
||||
| `--file-prefix` | `--conf` or `track_ch` | `Tracking.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/tracking-quality` | Output directory for PNGs. |
|
||||
| `--sampling-frequency` | `--conf` or `4000000.0` | Signal sampling frequency in Hz. |
|
||||
| `--channels` | `--conf` or `5` | Number of channels to read. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| `--signal-type` | `--conf` or `1C` | GNSS-SDR signal code used to restrict channel ranges and label traces; omitted with multi-signal `--conf` means all configured signals. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
|
||||
The C/N0 legend labels each trace as `<signal-type> PRN <PRN>` (e.g.
|
||||
`1C PRN 9`); the carrier-lock legend labels traces as `SV <signal-type> PRN
|
||||
<PRN>`.
|
||||
`1C PRN 9`); the carrier-lock legend labels traces as
|
||||
`SV <signal-type> PRN <PRN>`.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -255,19 +260,19 @@ channels.
|
||||
|
||||
Input pattern: `<input-path>/<file-prefix><channel>.dat`.
|
||||
|
||||
| Option | Default | Description |
|
||||
| -------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the telemetry `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer telemetry dump prefix and channel range. |
|
||||
| `--file-prefix` | `--conf` or `telemetry` | `TelemetryDecoder.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/telemetry` | Output directory for PNGs. |
|
||||
| `--channels` | `--conf` or `18` | Number of channels to try reading; missing channels are skipped. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| `--signal-type CODE` | inferred if needed | GNSS-SDR signal code used to select channel ranges and dump filenames from `--conf`. |
|
||||
| `--channel-a` | `--conf` or `0` | First channel number to plot. |
|
||||
| `--channel-b` | `--conf` or `5` | Second channel number to plot. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| Option | Default | Description |
|
||||
| -------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the telemetry `.dat` dumps. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer telemetry dump prefix and channel range. |
|
||||
| `--file-prefix` | `--conf` or `telemetry` | `TelemetryDecoder.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/telemetry` | Output directory for PNGs. |
|
||||
| `--channels` | `--conf` or `18` | Number of channels to try reading; missing channels are skipped. |
|
||||
| `--first-channel` | `--conf` or `0` | First channel number in the dump filenames. |
|
||||
| `--signal-type CODE` | inferred if needed | GNSS-SDR signal code used to select channel ranges and dump filenames from `--conf`. |
|
||||
| `--channel-a` | `--conf` or `0` | First channel number to plot. |
|
||||
| `--channel-b` | `--conf` or `5` | Second channel number to plot. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -284,15 +289,15 @@ phase, Doppler frequency, and captured PRNs across channels.
|
||||
|
||||
Input pattern: `<input-path>/<file-prefix>.dat` (single file).
|
||||
|
||||
| Option | Default | Description |
|
||||
| -------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the observables dump. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer observables dump filename and total channel count. |
|
||||
| `--file-prefix` | `--conf` or `observables.dat` | `Observables.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/hybrid-observables` | Output directory for PNGs. |
|
||||
| `--channels` | `--conf` or `5` | Number of observable channels in the dump. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| Option | Default | Description |
|
||||
| -------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the observables dump. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer observables dump filename and total channel count. |
|
||||
| `--file-prefix` | `--conf` or `observables.dat` | `Observables.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/hybrid-observables` | Output directory for PNGs. |
|
||||
| `--channels` | `--conf` or `5` | Number of observable channels in the dump. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -311,20 +316,20 @@ given.
|
||||
|
||||
Input pattern: `<input-path>/<file-prefix>.dat` (single file).
|
||||
|
||||
| Option | Default | Description |
|
||||
| ----------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the PVT dump. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer PVT dump filename and navigation solution period. |
|
||||
| `--file-prefix` | `--conf` or `PVT.dat` | `PVT.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/pvt` | Output directory for PNGs and maps. |
|
||||
| `--nav-sol-period` | `--conf` or `10.0` | Navigation solution period in milliseconds. |
|
||||
| `--true-position E_UTM N_UTM U_UTM` | unset (NaN) | Reference receiver position in UTM, used for error plots. |
|
||||
| `--plot-skyplot` | off | Try to generate the sky-plot panel. |
|
||||
| `--no-position` | position plot on | Skip the position/map diagnostic (avoids the `folium` dependency). |
|
||||
| `--one-vs-time NAME` | `X_vel`, `Tot_Vel` | `navSolutions` variable to plot versus time. Repeatable. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| `--open-maps` | off | Open the generated folium map HTML files in a browser. |
|
||||
| Option | Default | Description |
|
||||
| ----------------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `-i`, `--input-path` | `.` | Directory containing the PVT dump. |
|
||||
| `--conf` | unset | GNSS-SDR configuration used to infer PVT dump filename and navigation solution period. |
|
||||
| `--file-prefix` | `--conf` or `PVT.dat` | `PVT.dump_filename` value (may include a directory/extension). |
|
||||
| `-o`, `--fig-path` | `plots/pvt` | Output directory for PNGs and maps. |
|
||||
| `--nav-sol-period` | `--conf` or `10.0` | Navigation solution period in milliseconds. |
|
||||
| `--true-position E_UTM N_UTM U_UTM` | unset (NaN) | Reference receiver position in UTM, used for error plots. |
|
||||
| `--plot-skyplot` | off | Try to generate the sky-plot panel. |
|
||||
| `--no-position` | position plot on | Skip the position/map diagnostic (avoids the `folium` dependency). |
|
||||
| `--one-vs-time NAME` | `X_vel`, `Tot_Vel` | `navSolutions` variable to plot versus time. Repeatable. |
|
||||
| `--show` | off | Display figures after saving. |
|
||||
| `--format` | `png` | Saved figure format: `png` (default), `pdf`, `eps`, `svg`, `jpg`. Vector formats embed fonts (publication-ready). |
|
||||
| `--open-maps` | off | Open the generated folium map HTML files in a browser. |
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ from lib.gnss_sdr_conf import (
|
||||
SIGNAL_TYPES,
|
||||
add_conf_argument,
|
||||
load_gnss_sdr_conf,
|
||||
signal_pretty_name,
|
||||
)
|
||||
from lib.plot_format import add_output_format_argument, apply_publication_style
|
||||
from lib.plotVEMLTracking import plotVEMLTracking
|
||||
@@ -216,6 +217,11 @@ def read_tracking_dumps(args):
|
||||
return dumps
|
||||
|
||||
|
||||
def prn_label(prns):
|
||||
prns = dict.fromkeys(int(prn) for prn in prns if int(prn))
|
||||
return "/".join(str(prn) for prn in prns) or "unknown"
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
args.fig_path.mkdir(parents=True, exist_ok=True)
|
||||
@@ -270,6 +276,14 @@ def main():
|
||||
/ args.sampling_frequency
|
||||
),
|
||||
}
|
||||
signal_name = signal_pretty_name(
|
||||
tracking.get("_signal_type") or DEFAULT_SIGNAL_TYPE
|
||||
)
|
||||
track_result["signalName"] = signal_name
|
||||
track_result["prnLabel"] = prn_label(track_result["PRN"])
|
||||
track_result["plotTitle"] = (
|
||||
f"{signal_name} PRN {track_result['prnLabel']}"
|
||||
)
|
||||
track_results.append(track_result)
|
||||
|
||||
plotVEMLTracking(index, track_results, settings)
|
||||
@@ -281,9 +295,12 @@ def main():
|
||||
track_result["prn_start_time_s"],
|
||||
[x / 1000 for x in tracking["carrier_doppler_hz"][start_sample:]],
|
||||
)
|
||||
plt.xlabel("Time(s)")
|
||||
plt.ylabel("Doppler(KHz)")
|
||||
plt.title(f"Doppler frequency channel {channel}")
|
||||
plt.xlabel("Time (s)")
|
||||
plt.ylabel("Doppler (kHz)")
|
||||
plt.title(
|
||||
f"Doppler frequency - {track_result['plotTitle']} "
|
||||
f"(channel {channel})"
|
||||
)
|
||||
plt.savefig(
|
||||
args.fig_path
|
||||
/ f"Doppler_freq_ch_{channel}.{args.output_format}"
|
||||
|
||||
@@ -39,25 +39,51 @@ SIGNAL_ORDER = (
|
||||
"J5",
|
||||
)
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SignalType:
|
||||
system: str
|
||||
n_chips: int
|
||||
pretty_name: str
|
||||
|
||||
def __iter__(self):
|
||||
# Keep compatibility with callers that unpack SIGNAL_TYPES entries as
|
||||
# (system, n_chips).
|
||||
yield self.system
|
||||
yield self.n_chips
|
||||
|
||||
|
||||
# GNSS-SDR signal nomenclature: each signal code maps to the system character
|
||||
# used in acquisition dump filenames and to its primary code length in chips.
|
||||
# used in acquisition dump filenames, its primary code length in chips, and a
|
||||
# human-friendly signal name for plot labels.
|
||||
SIGNAL_TYPES = {
|
||||
"1C": ("G", 1023), # GPS L1 C/A
|
||||
"2S": ("G", 10230), # GPS L2C
|
||||
"L5": ("G", 10230), # GPS L5
|
||||
"1B": ("E", 4092), # Galileo E1B
|
||||
"5X": ("E", 10230), # Galileo E5a
|
||||
"7X": ("E", 10230), # Galileo E5b
|
||||
"E6": ("E", 5115), # Galileo E6
|
||||
"1G": ("R", 511), # GLONASS L1
|
||||
"2G": ("R", 511), # GLONASS L2
|
||||
"B1": ("C", 2046), # BeiDou B1I
|
||||
"B3": ("C", 10230), # BeiDou B3I
|
||||
"J1": ("J", 1023), # QZSS L1 C/A
|
||||
"J5": ("J", 10230), # QZSS L5
|
||||
"1C": SignalType("G", 1023, "GPS L1 C/A"),
|
||||
"2S": SignalType("G", 10230, "GPS L2C"),
|
||||
"L5": SignalType("G", 10230, "GPS L5"),
|
||||
"1B": SignalType("E", 4092, "Galileo E1B"),
|
||||
"5X": SignalType("E", 10230, "Galileo E5a"),
|
||||
"7X": SignalType("E", 10230, "Galileo E5b"),
|
||||
"E6": SignalType("E", 5115, "Galileo E6"),
|
||||
"1G": SignalType("R", 511, "GLONASS L1 C/A"),
|
||||
"2G": SignalType("R", 511, "GLONASS L2 C/A"),
|
||||
"B1": SignalType("C", 2046, "BeiDou B1I"),
|
||||
"B3": SignalType("C", 10230, "BeiDou B3I"),
|
||||
"J1": SignalType("J", 1023, "QZSS L1 C/A"),
|
||||
"J5": SignalType("J", 10230, "QZSS L5"),
|
||||
}
|
||||
|
||||
N_CHIPS = {(system, code): nc for code, (system, nc) in SIGNAL_TYPES.items()}
|
||||
N_CHIPS = {
|
||||
(signal_type.system, code): signal_type.n_chips
|
||||
for code, signal_type in SIGNAL_TYPES.items()
|
||||
}
|
||||
|
||||
|
||||
def signal_pretty_name(signal_type):
|
||||
if signal_type is None:
|
||||
return ""
|
||||
metadata = SIGNAL_TYPES.get(signal_type.upper())
|
||||
if metadata is None:
|
||||
return signal_type
|
||||
return metadata.pretty_name
|
||||
|
||||
|
||||
class ConfigError(ValueError):
|
||||
|
||||
@@ -46,12 +46,17 @@ def plotVEMLTracking(channelNr, trackResults, settings):
|
||||
|
||||
# Protection - if the list contains incorrect channel numbers
|
||||
if channelNr in list(range(1,settings["numberOfChannels"]+1)):
|
||||
track_result = trackResults[channelNr-1]
|
||||
prn_label = track_result.get('prnLabel', str(track_result["PRN"][0]))
|
||||
plot_title = track_result.get('plotTitle', f'PRN {prn_label}')
|
||||
|
||||
plt.figure(figsize=(1920 / 120, 1080 / 120))
|
||||
plt.clf()
|
||||
plt.gcf().canvas.manager.set_window_title(
|
||||
f'Channel {display_channel} (PRN '
|
||||
f'{trackResults[channelNr-1]["PRN"][0]}) results')
|
||||
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1,
|
||||
f'Channel {display_channel} - {plot_title} results')
|
||||
plt.suptitle(f'{plot_title} (channel {display_channel})',
|
||||
fontweight='bold')
|
||||
plt.subplots_adjust(left=0.1, right=0.9, top=0.86, bottom=0.1,
|
||||
hspace=0.4, wspace=0.4)
|
||||
|
||||
# Extract timeAxis and time_label
|
||||
|
||||
+202
-33
@@ -33,6 +33,7 @@ from lib.gnss_sdr_conf import (
|
||||
SIGNAL_TYPES,
|
||||
add_conf_argument,
|
||||
load_gnss_sdr_conf,
|
||||
signal_pretty_name,
|
||||
)
|
||||
from lib.plot_format import add_output_format_argument, apply_publication_style
|
||||
|
||||
@@ -46,6 +47,8 @@ DEFAULT_SAT = 1
|
||||
DEFAULT_CHANNEL = 0
|
||||
DEFAULT_EXECUTION = 1
|
||||
DEFAULT_SIGNAL_TYPE = "1C"
|
||||
MAX_LITE_SURFACE_CODE_POINTS = 3200
|
||||
MAX_LITE_SURFACE_DOPPLER_POINTS = 250
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -176,6 +179,20 @@ def parse_args():
|
||||
default=3,
|
||||
help="Samples per chip used by the light grid interpolation.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--samples-per-doppler-step",
|
||||
type=int,
|
||||
default=5,
|
||||
help="Interpolated samples per Doppler step used by the light grid "
|
||||
"interpolation.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--surface-smoothing",
|
||||
type=float,
|
||||
default=2.0,
|
||||
help="Gaussian smoothing sigma, in interpolated surface samples, "
|
||||
"applied only to the lite 3D view. Use 0 to disable.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--samples-per-code",
|
||||
type=int,
|
||||
@@ -310,6 +327,52 @@ def matching_dump_prefixes(input_path):
|
||||
return sorted(prefixes)
|
||||
|
||||
|
||||
def configured_doppler_axis(doppler_max, doppler_step, n_dop_bins, file_path):
|
||||
import numpy as np
|
||||
|
||||
doppler_max = abs(float(doppler_max))
|
||||
doppler_step = abs(float(doppler_step))
|
||||
if doppler_step == 0:
|
||||
raise ValueError(f"{file_path}: doppler_step must be non-zero")
|
||||
|
||||
freq = np.arange(-doppler_max, doppler_max + doppler_step / 2, doppler_step)
|
||||
if len(freq) == n_dop_bins:
|
||||
return freq
|
||||
|
||||
legacy_freq = np.arange(n_dop_bins) * doppler_step - doppler_max
|
||||
if len(freq) - 1 == n_dop_bins:
|
||||
print(
|
||||
f"Warning: {file_path.name}: acq_grid has {n_dop_bins} Doppler "
|
||||
f"bins, one fewer than the inclusive configured axis from "
|
||||
f"{-doppler_max:g} Hz to {doppler_max:g} Hz in "
|
||||
f"{doppler_step:g} Hz steps. Plotting the available bins from "
|
||||
f"{legacy_freq[0]:g} Hz to {legacy_freq[-1]:g} Hz."
|
||||
)
|
||||
return legacy_freq
|
||||
|
||||
print(
|
||||
f"Warning: {file_path.name}: configured Doppler axis has {len(freq)} "
|
||||
f"bins from {-doppler_max:g} Hz to {doppler_max:g} Hz in "
|
||||
f"{doppler_step:g} Hz steps, but acq_grid has {n_dop_bins} columns. "
|
||||
"Plotting the available columns over the configured Doppler range."
|
||||
)
|
||||
return np.linspace(-doppler_max, doppler_max, n_dop_bins)
|
||||
|
||||
|
||||
def expected_doppler_bin_counts(doppler_max, doppler_step):
|
||||
import numpy as np
|
||||
|
||||
doppler_max = abs(float(doppler_max))
|
||||
doppler_step = abs(float(doppler_step))
|
||||
if doppler_step == 0:
|
||||
return set()
|
||||
|
||||
inclusive_count = len(
|
||||
np.arange(-doppler_max, doppler_max + doppler_step / 2, doppler_step)
|
||||
)
|
||||
return {inclusive_count, max(1, inclusive_count - 1)}
|
||||
|
||||
|
||||
def read_acquisition_dump(file_path, n_chips, positive_only):
|
||||
import h5py
|
||||
import numpy as np
|
||||
@@ -323,21 +386,77 @@ def read_acquisition_dump(file_path, n_chips, positive_only):
|
||||
if positive_acq != 1:
|
||||
return None
|
||||
|
||||
acq_grid = data["acq_grid"][:]
|
||||
n_fft, n_dop_bins = acq_grid.shape
|
||||
d_max, f_max = np.unravel_index(np.argmax(acq_grid), acq_grid.shape)
|
||||
doppler_step = data["doppler_step"][0]
|
||||
doppler_max = data["doppler_max"][0]
|
||||
freq = np.arange(n_dop_bins) * doppler_step - doppler_max
|
||||
acq_grid = data["acq_grid"][:]
|
||||
expected_doppler_bins = expected_doppler_bin_counts(
|
||||
doppler_max,
|
||||
doppler_step,
|
||||
)
|
||||
if (
|
||||
acq_grid.shape[1] not in expected_doppler_bins
|
||||
and acq_grid.shape[0] in expected_doppler_bins
|
||||
):
|
||||
acq_grid = acq_grid.T
|
||||
|
||||
n_fft, n_dop_bins = acq_grid.shape
|
||||
freq = configured_doppler_axis(
|
||||
doppler_max,
|
||||
doppler_step,
|
||||
n_dop_bins,
|
||||
file_path,
|
||||
)
|
||||
d_max, f_max = np.unravel_index(np.argmax(acq_grid), acq_grid.shape)
|
||||
delay = np.arange(n_fft) / n_fft * n_chips
|
||||
|
||||
return acq_grid, n_fft, d_max, f_max, doppler_step, doppler_max, freq, delay
|
||||
|
||||
|
||||
def plot_dump(file_path, fig_path, image_name_root, n_chips, args):
|
||||
def acquisition_plot_title(metadata):
|
||||
signal_name = signal_pretty_name(metadata["signal"])
|
||||
return (
|
||||
f"{signal_name} PRN {metadata['sat']} "
|
||||
f"(channel {metadata['channel']}, execution {metadata['execution']})"
|
||||
)
|
||||
|
||||
|
||||
def interpolated_acquisition_grid(delay, freq, acq_grid, args, n_chips):
|
||||
import numpy as np
|
||||
from scipy.ndimage import gaussian_filter
|
||||
from scipy.interpolate import RectBivariateSpline
|
||||
|
||||
if len(delay) < 2 or len(freq) < 2:
|
||||
return delay, freq, acq_grid
|
||||
|
||||
samples_per_chip = max(1, args.samples_per_chip)
|
||||
samples_per_doppler_step = max(1, args.samples_per_doppler_step)
|
||||
delay_points = min(
|
||||
samples_per_chip * n_chips,
|
||||
MAX_LITE_SURFACE_CODE_POINTS,
|
||||
)
|
||||
freq_points = min(
|
||||
(len(freq) - 1) * samples_per_doppler_step + 1,
|
||||
MAX_LITE_SURFACE_DOPPLER_POINTS,
|
||||
)
|
||||
delay_interp = np.linspace(delay[0], delay[-1], max(2, delay_points))
|
||||
freq_interp = np.linspace(freq[0], freq[-1], max(2, freq_points))
|
||||
|
||||
kx = min(3, len(delay) - 1)
|
||||
ky = min(3, len(freq) - 1)
|
||||
spline = RectBivariateSpline(delay, freq, acq_grid, kx=kx, ky=ky)
|
||||
grid_interp = spline(delay_interp, freq_interp)
|
||||
if args.surface_smoothing > 0:
|
||||
grid_interp = gaussian_filter(
|
||||
grid_interp,
|
||||
sigma=args.surface_smoothing,
|
||||
mode="nearest",
|
||||
)
|
||||
return delay_interp, freq_interp, grid_interp
|
||||
|
||||
|
||||
def plot_dump(file_path, fig_path, image_name_root, n_chips, args, metadata=None):
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from scipy.interpolate import CubicSpline
|
||||
|
||||
dump = read_acquisition_dump(file_path, n_chips, args.plot_positive_acqs)
|
||||
if dump is None:
|
||||
@@ -354,28 +473,65 @@ def plot_dump(file_path, fig_path, image_name_root, n_chips, args):
|
||||
delay,
|
||||
) = dump
|
||||
|
||||
if metadata is None:
|
||||
metadata = parse_dump_name(file_path)
|
||||
plot_title = acquisition_plot_title(metadata) if metadata else str(file_path)
|
||||
|
||||
fig = plt.figure()
|
||||
plt.gcf().canvas.manager.set_window_title(str(file_path))
|
||||
if not args.lite_view:
|
||||
ax = fig.add_subplot(111, projection="3d")
|
||||
x_axis, y_axis = np.meshgrid(freq, delay)
|
||||
ax.plot_surface(x_axis, y_axis, acq_grid, cmap="viridis")
|
||||
x_axis, y_axis = np.meshgrid(freq, delay, indexing="xy")
|
||||
ax.plot_surface(
|
||||
x_axis,
|
||||
y_axis,
|
||||
acq_grid,
|
||||
cmap="viridis",
|
||||
linewidth=0,
|
||||
edgecolor="none",
|
||||
antialiased=False,
|
||||
)
|
||||
ax.set_ylim([min(delay), max(delay)])
|
||||
else:
|
||||
delay_interp = (
|
||||
np.arange(args.samples_per_chip * n_chips) / args.samples_per_chip
|
||||
delay_interp, freq_interp, grid_interp = interpolated_acquisition_grid(
|
||||
delay,
|
||||
freq,
|
||||
acq_grid,
|
||||
args,
|
||||
n_chips,
|
||||
)
|
||||
spline = CubicSpline(delay, acq_grid)
|
||||
grid_interp = spline(delay_interp)
|
||||
ax = fig.add_subplot(111, projection="3d")
|
||||
x_axis, y_axis = np.meshgrid(freq, delay_interp)
|
||||
ax.plot_surface(x_axis, y_axis, grid_interp, cmap="inferno")
|
||||
x_axis, y_axis = np.meshgrid(freq_interp, delay_interp, indexing="xy")
|
||||
ax.plot_surface(
|
||||
x_axis,
|
||||
y_axis,
|
||||
grid_interp,
|
||||
cmap="inferno",
|
||||
rstride=1,
|
||||
cstride=1,
|
||||
linewidth=0,
|
||||
edgecolor="none",
|
||||
antialiased=False,
|
||||
)
|
||||
ax.set_ylim([min(delay_interp), max(delay_interp)])
|
||||
|
||||
peak_doppler = freq[f_max]
|
||||
peak_delay = delay[d_max]
|
||||
peak_value = acq_grid[d_max, f_max]
|
||||
ax.scatter(
|
||||
[peak_doppler],
|
||||
[peak_delay],
|
||||
[peak_value],
|
||||
color="red",
|
||||
s=30,
|
||||
label="Peak",
|
||||
)
|
||||
ax.set_xlabel("Doppler shift (Hz)")
|
||||
ax.set_xlim([min(freq), max(freq)])
|
||||
ax.set_ylabel("Code delay (chips)")
|
||||
ax.set_zlabel("Test Statistics")
|
||||
ax.set_title(plot_title)
|
||||
ax.legend(loc="upper right")
|
||||
plt.tight_layout()
|
||||
plt.savefig(fig_path / f"{image_name_root}_3D.{args.output_format}")
|
||||
if not args.show:
|
||||
@@ -383,24 +539,25 @@ def plot_dump(file_path, fig_path, image_name_root, n_chips, args):
|
||||
|
||||
fig2, axes = plt.subplots(2, 1, figsize=(8, 6))
|
||||
plt.gcf().canvas.manager.set_window_title(str(file_path))
|
||||
fig2.suptitle(plot_title)
|
||||
axes[0].plot(freq, acq_grid[d_max, :])
|
||||
axes[0].axvline(peak_doppler, color="red", linestyle="--", linewidth=0.8)
|
||||
axes[0].set_xlim([min(freq), max(freq)])
|
||||
axes[0].set_xlabel("Doppler shift (Hz)")
|
||||
axes[0].set_ylabel("Test statistics")
|
||||
axes[0].set_title(
|
||||
f"Fixed code delay to {(d_max - 1) / n_fft * n_chips} chips"
|
||||
)
|
||||
axes[0].set_title(f"Doppler cut at code delay = {peak_delay:g} chips")
|
||||
|
||||
normalization = (args.samples_per_code ** 4) * args.input_power
|
||||
axes[1].plot(delay, acq_grid[:, f_max] / normalization)
|
||||
axes[1].axvline(peak_delay, color="red", linestyle="--", linewidth=0.8)
|
||||
axes[1].set_xlim([min(delay), max(delay)])
|
||||
axes[1].set_xlabel("Code delay (chips)")
|
||||
axes[1].set_ylabel("Test statistics")
|
||||
axes[1].set_title(
|
||||
f"Doppler wipe-off = {(f_max - 1) * doppler_step - doppler_max} Hz"
|
||||
f"Code-delay cut at Doppler wipe-off = {peak_doppler:g} Hz"
|
||||
)
|
||||
|
||||
plt.tight_layout()
|
||||
fig2.tight_layout(rect=(0, 0, 1, 0.95))
|
||||
plt.savefig(fig_path / f"{image_name_root}_2D.{args.output_format}")
|
||||
if not args.show:
|
||||
plt.close(fig2)
|
||||
@@ -425,17 +582,15 @@ def single_file_path(args):
|
||||
f"{base}_{system}_{signal}_ch_{channel}_"
|
||||
f"{execution}_sat_{sat}.mat"
|
||||
)
|
||||
image_name_root = image_name_from_metadata(
|
||||
args.output_basename,
|
||||
{
|
||||
"system": system,
|
||||
"signal": signal,
|
||||
"channel": channel,
|
||||
"execution": execution,
|
||||
"sat": sat,
|
||||
},
|
||||
)
|
||||
return directory / filename, image_name_root, n_chips
|
||||
metadata = {
|
||||
"system": system,
|
||||
"signal": signal,
|
||||
"channel": channel,
|
||||
"execution": execution,
|
||||
"sat": sat,
|
||||
}
|
||||
image_name_root = image_name_from_metadata(args.output_basename, metadata)
|
||||
return directory / filename, image_name_root, n_chips, metadata
|
||||
|
||||
|
||||
def image_name_from_metadata(output_basename, metadata):
|
||||
@@ -486,10 +641,17 @@ def main():
|
||||
apply_publication_style()
|
||||
|
||||
if not args.plot_all_files:
|
||||
file_path, image_name_root, n_chips = single_file_path(args)
|
||||
file_path, image_name_root, n_chips, metadata = single_file_path(args)
|
||||
if not file_path.exists():
|
||||
raise FileNotFoundError(f"dump file not found: {file_path}")
|
||||
plot_dump(file_path, args.fig_path, image_name_root, n_chips, args)
|
||||
plot_dump(
|
||||
file_path,
|
||||
args.fig_path,
|
||||
image_name_root,
|
||||
n_chips,
|
||||
args,
|
||||
metadata,
|
||||
)
|
||||
show_figures(args)
|
||||
return
|
||||
|
||||
@@ -530,7 +692,14 @@ def main():
|
||||
args.output_basename,
|
||||
metadata,
|
||||
)
|
||||
if plot_dump(file_path, args.fig_path, image_name_root, n_chips, args):
|
||||
if plot_dump(
|
||||
file_path,
|
||||
args.fig_path,
|
||||
image_name_root,
|
||||
n_chips,
|
||||
args,
|
||||
metadata,
|
||||
):
|
||||
plotted += 1
|
||||
|
||||
if not found_paths:
|
||||
|
||||
Reference in New Issue
Block a user