Пример #1
0
def test_plt_colormaps():
    spec, spec_r = spectral()
    ja, ja_r = jade()
    plt_colormaps(spec, spec_r, ja, ja_r, ".")
    png = Path("colormaps.png")
    assert png.is_file() is True
    if png.is_file() is True:
        png.unlink()
Пример #2
0
----------
"""

import argparse
from pathlib import Path

import healpy as hp
import matplotlib
import numpy as np
from embers.rf_tools.colormaps import spectral
from matplotlib import pyplot as plt
from numpy.polynomial import polynomial as poly
from scipy.stats import median_absolute_deviation as mad

matplotlib.use("Agg")
_spec, _ = spectral()
colors = _spec([0.72, 0.30, 0.18])

parser = argparse.ArgumentParser(description="""
    Null Sats paper plot
    """)

parser.add_argument(
    "--out_dir",
    metavar="\b",
    default="../embers_out/paper_plots",
    help="Output directory. Default=../embers_out/paper_plots",
)
parser.add_argument(
    "--map_dir",
    metavar="\b",
Пример #3
0
def good_chans(
    ali_file,
    chrono_file,
    sat_id,
    sat_thresh,
    noi_thresh,
    pow_thresh,
    occ_thresh,
    timestamp,
    out_dir,
    plots=None,
):
    """Determine the channels a satellite could occupy, in a 30 minute observation

    Ephemeris from :samp:`chrono_file` is used to select a temporal :samp:`window`
    of the rf power array, within which the satellite is above the horizon. Looping
    through the frequency channels, a :samp:`noi_thresh`, :samp:`pow_thresh`, :samp:`occ_thresh`
    are used to identify possible channels occupied by the :samp:`sat_id`. If more than one
    channel passes the three thresholds, the channel with the highest window occupancy is
    selected.

    .. code-block:: python

        from embers.sat_utils.sat_channels import good_chans

        ali_file = "~/embers_out/rf0XX_S06XX_2019-10-10-02:30_aligned.npz"
        chrono_file = "~/embers_out/2019-10-10-02:30.json"
        sat_id = "44387"
        sat_thresh = 1
        noi_thresh = 3
        pow_thresh = 20
        occ_thresh = 0.80
        timestamp = "2019-10-10-02:30"
        out_dir = "./embers_out"
        plots = True

        good_chan = good_chans(
                        ali_file,
                        chrono_file,
                        sat_id,
                        sat_thresh,
                        noi_thresh,
                        pow_thresh,
                        occ_thresh,
                        timestamp,
                        out_dir,
                        plots=plots)

        print(good_chan)
        >>> 59

    :param ali_file: Path to a :samp:`npz` aligned file from :func:`~embers.rf_tools.align_data.save_aligned` :class:`~str`
    :param chrono_file: Path to chrono ephem json file from :func:`~embers.sat_utils.chrono_ephem.save_chrono_ephem` :class:`~str`
    :param sat_id: Norad catalogue ID :class:`~str`
    :param sat_thresh: Satellite threshold from :func:`~embers.sat_utils.sat_channels.noise_floor` :class:`~int`
    :param noi_thresh: Noise threshold from :func:`~embers.sat_utils.sat_channels.noise_floor` :class:`~int`
    :param pow_thresh: Minimum power threshold in :samp:`dBm` :class:`~float`
    :param occ_thresh: Window occupation threshold. Minimum fractional signal above the noise floor in window :class:`~float`
    :param timestamp: Time at start of observation in format :samp:`YYYY-MM-DD-HH:MM` :class:`~str`
    :param out_dir: Path to output directory to save plots :class:`~str`
    :param plots: If :samp:`True`, disagnostic plots are generated and saved to :samp:`out_dir`

    :returns:
        - good_chan: The channel number of most probable channel for :samp:`sat_id`
        - good_chan may be :samp:`None`, if no possible channels were identified

    """

    spec, _ = spectral()

    power, _, times = read_aligned(ali_file=ali_file)
    p_med = np.median(power)

    # Determine noise threshold
    noise_threshold = noise_floor(sat_thresh, noi_thresh, power)

    with open(chrono_file) as chrono:
        chrono_ephem = json.load(chrono)

        # All satellites in chrono ephem json file
        norad_list = [
            chrono_ephem[s]["sat_id"][0] for s in range(len(chrono_ephem))
        ]

        # Index of sat_id in chrono ephem json file
        norad_index = norad_list.index(sat_id)

        # Extract ephemeris for sat_id
        norad_ephem = chrono_ephem[norad_index]

        rise_ephem = norad_ephem["time_array"][0]
        set_ephem = norad_ephem["time_array"][-1]

        # indices of times, when sat rose and set
        intvl = time_filter(rise_ephem, set_ephem, np.asarray(times))

        # Window start, stop
        w_start, w_stop = intvl
        window_len = w_stop - w_start + 1

        # Slice the power/times arrays to the times of sat pass
        power_c = power[w_start:w_stop + 1, :]
        times_c = times[w_start:w_stop + 1]

        # possible identified channels
        possible_chans = []
        # window occupancy of possible channels
        occu_list = []

        # Loop over every channel
        for s_chan in range(len(power_c[0])):

            channel_power = power_c[:, s_chan]

            # Percentage of signal occupancy above noise threshold
            window_occupancy = (np.where(
                channel_power >= noise_threshold))[0].size / window_len

            # Power threshold below which satellites aren't counted
            # Only continue if there is signal for more than 80% of satellite pass
            if (max(channel_power) >= p_med + pow_thresh
                    and occ_thresh <= window_occupancy < 1.00):

                # If satellite window begins from the start of the observation
                if times[0] == times_c[0]:
                    # last 10 data points (10 seconds) are below the noise threshold
                    if (all(p < noise_threshold
                            for p in channel_power[-11:-1])) is True:
                        occu_list.append(window_occupancy)
                        possible_chans.append(s_chan)

                        if plots is True:
                            plt = plt_channel(
                                times_c,
                                channel_power,
                                p_med,
                                s_chan,
                                [
                                    np.amin(channel_power) - 1,
                                    np.amax(channel_power) + 1,
                                ],
                                noise_threshold,
                                pow_thresh + p_med,
                            )
                            date = re.search(r"\d{4}.\d{2}.\d{2}",
                                             timestamp)[0]
                            plt_dir = Path(
                                f"{out_dir}/window_plots/{date}/{timestamp}")
                            plt_dir.mkdir(parents=True, exist_ok=True)
                            plt.savefig(
                                f"{plt_dir}/{sat_id}_channel_{s_chan}_{window_occupancy:.2f}.png"
                            )
                            plt.close()

                # if the satellite window ends and the end of the observation
                elif times[-1] == times_c[-1]:

                    # first 10 data points (10 seconds) are below the noise threshold
                    if (all(p < noise_threshold
                            for p in channel_power[:10])) is True:
                        occu_list.append(window_occupancy)
                        possible_chans.append(s_chan)

                        if plots is True:
                            plt = plt_channel(
                                times_c,
                                channel_power,
                                p_med,
                                s_chan,
                                [
                                    np.amin(channel_power) - 1,
                                    np.amax(channel_power) + 1,
                                ],
                                noise_threshold,
                                pow_thresh + p_med,
                            )
                            date = re.search(r"\d{4}.\d{2}.\d{2}",
                                             timestamp)[0]
                            plt_dir = Path(
                                f"{out_dir}/window_plots/{date}/{timestamp}")
                            plt_dir.mkdir(parents=True, exist_ok=True)
                            plt.savefig(
                                f"{plt_dir}/{sat_id}_channel_{s_chan}_{window_occupancy:.2f}.png"
                            )
                            plt.close()

                # satellite window completely within the observation
                else:
                    # first and last 10 data points (10 seconds) are below the noise threshold
                    if (all(p < noise_threshold for p in channel_power[:10])
                            and all(p < noise_threshold
                                    for p in channel_power[-11:-1])) is True:
                        occu_list.append(window_occupancy)
                        possible_chans.append(s_chan)

                        if plots is True:
                            plt = plt_channel(
                                times_c,
                                channel_power,
                                p_med,
                                s_chan,
                                [
                                    np.amin(channel_power) - 1,
                                    np.amax(channel_power) + 1,
                                ],
                                noise_threshold,
                                pow_thresh + p_med,
                            )
                            date = re.search(r"\d{4}.\d{2}.\d{2}",
                                             timestamp)[0]
                            plt_dir = Path(
                                f"{out_dir}/window_plots/{date}/{timestamp}")
                            plt_dir.mkdir(parents=True, exist_ok=True)
                            plt.savefig(
                                f"{plt_dir}/{sat_id}_channel_{s_chan}_{window_occupancy:.2f}.png"
                            )
                            plt.close()

        # If channels are identified in the 30 min obs
        n_chans = len(possible_chans)
        if n_chans > 0:

            # The most probable channel is one with the highest occupation
            good_chan = possible_chans[occu_list.index(max(occu_list))]

            if plots is True:
                plt = plt_window_chans(
                    power,
                    sat_id,
                    w_start,
                    w_stop,
                    spec,
                    chs=possible_chans,
                    good_ch=good_chan,
                )
                date = re.search(r"\d{4}.\d{2}.\d{2}", timestamp)[0]
                plt_dir = Path(f"{out_dir}/window_plots/{date}/{timestamp}")
                plt_dir.mkdir(parents=True, exist_ok=True)
                plt.savefig(f"{plt_dir}/{sat_id}_waterfall_{good_chan}.png")
                plt.close()

            return good_chan

        else:
            if plots is True:
                plt = plt_window_chans(power, sat_id, w_start, w_stop, spec)
                date = re.search(r"\d{4}.\d{2}.\d{2}", timestamp)[0]
                plt_dir = Path(f"{out_dir}/window_plots/{date}/{timestamp}")
                plt_dir.mkdir(parents=True, exist_ok=True)
                plt.savefig(f"{plt_dir}/{sat_id}_waterfall_window.png")
                plt.close()

            return None
Пример #4
0
# Code developed by Jack Line and adapted here
# https://github.com/JLBLine/MWA_ORBCOMM

from pathlib import Path

import healpy as hp
import matplotlib
import numpy as np
import pkg_resources
from embers.rf_tools.colormaps import spectral
from embers.tile_maps.beam_utils import plot_healpix
from matplotlib import pyplot as plt
from scipy.interpolate import RectSphereBivariateSpline

matplotlib.use("Agg")
cmap, _ = spectral()


def create_model(nside, file_name=None):
    """Takes feko .ffe reference model, converts into healpix and smooths the response

    :param nside: Healpix nside
    :param file_name: Path to :samp:`.ffe` feko model of reference tiles

    :returns:
        - :class:`tuple` of (beam_response, theta_mesh, phi_mesh, power, theta)

    """

    # Make an empty array for healpix projection
    len_empty_healpix = hp.nside2npix(nside)
Пример #5
0
def test_spectral():
    spec, _ = spectral()
    assert type(spec).__name__ == "ListedColormap"
Пример #6
0
def test_spectral_r():
    _, spec_r = spectral()
    assert type(spec_r).__name__ == "ListedColormap"
Пример #7
0
"""
Colormaps
=========

Visualise custom colormaps used by embers.
Creates sample plot of ember colormaps
saved to :samp:`./embers_out/rf_tools/colormaps.png`

"""

import argparse
from pathlib import Path

from embers.rf_tools.colormaps import jade, plt_colormaps, spectral

_spec, _spec_r = spectral()
_jade, _jade_r = jade()


def main():
    """
    Preview *EMBERS* two beautiful custom colormaps - :func:`~embers.rf_tools.colormaps.spectral` & :func:`~embers.rf_tools.colormaps.jade`.
    The :samp:`spectral` colormap is non-linear and is just used to visualise raw data and maximize dynamic range, while :samp:`jade` is
    perceptually uniform and sequential and is suitable for science. To get a preview of how amazing they are

    .. code-block:: console

        $ colormaps --help

    """
    _parser = argparse.ArgumentParser(description="""