From a62e05c9564045044df734fd3723b3f665ad91ae Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 29 Dec 2017 06:43:49 +0100 Subject: DPD: Make logging to file optional in all modules, simplify apply_adapt_dumps --- dpd/src/Adapt.py | 10 ++++++++-- dpd/src/Const.py | 6 +++--- dpd/src/Dab_Util.py | 15 +++++++++------ dpd/src/ExtractStatistic.py | 8 +++++--- dpd/src/MER.py | 8 +++++--- dpd/src/Measure.py | 2 -- dpd/src/Measure_Shoulders.py | 8 +++++++- dpd/src/Model.py | 6 ++++++ dpd/src/Model_AM.py | 8 +++++--- dpd/src/Model_Lut.py | 6 ++++-- dpd/src/Model_PM.py | 8 +++++--- dpd/src/Model_Poly.py | 6 ++++-- dpd/src/RX_Agc.py | 8 +++++++- dpd/src/Symbol_align.py | 4 ++-- dpd/src/TX_Agc.py | 5 ++++- dpd/src/phase_align.py | 7 +++++-- dpd/src/subsample_align.py | 8 +++++--- 17 files changed, 84 insertions(+), 39 deletions(-) (limited to 'dpd/src') diff --git a/dpd/src/Adapt.py b/dpd/src/Adapt.py index 7e19a2c..c78c920 100644 --- a/dpd/src/Adapt.py +++ b/dpd/src/Adapt.py @@ -16,7 +16,10 @@ import os import datetime import pickle -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None LUT_LEN = 32 FORMAT_POLY = 1 @@ -226,7 +229,10 @@ class Adapt: """Backup current settings to a file""" dt = datetime.datetime.now().isoformat() if path is None: - path = logging_path + "/" + dt + "_adapt.pkl" + if logging_path is not None: + path = logging_path + "/" + dt + "_adapt.pkl" + else: + raise Exception("Cannot dump Adapt without either logging_path or path set") d = { "txgain": self.get_txgain(), "rxgain": self.get_rxgain(), diff --git a/dpd/src/Const.py b/dpd/src/Const.py index 6c9bafa..d80cfac 100644 --- a/dpd/src/Const.py +++ b/dpd/src/Const.py @@ -73,14 +73,14 @@ class Const: self.MPM_tx_min = 0.1 # Constants for TX_Agc - self.TAGC_max_txgain = 89 # USRP specific + self.TAGC_max_txgain = 89 # USRP B200 specific self.TAGC_tx_median_target = target_median self.TAGC_tx_median_max = self.TAGC_tx_median_target * 1.4 self.TAGC_tx_median_min = self.TAGC_tx_median_target / 1.4 # Constants for RX_AGC - self.RAGC_min_rxgain = 25 # USRP specific - self.RAGC_rx_median_target = self.TAGC_tx_median_target + self.RAGC_min_rxgain = 25 # USRP B200 specific + self.RAGC_rx_median_target = target_median # The MIT License (MIT) # diff --git a/dpd/src/Dab_Util.py b/dpd/src/Dab_Util.py index 2021f38..56c9503 100644 --- a/dpd/src/Dab_Util.py +++ b/dpd/src/Dab_Util.py @@ -9,7 +9,10 @@ import datetime import os import logging -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np import matplotlib @@ -53,7 +56,7 @@ class Dab_Util: off = sig_rec.shape[0] c = np.abs(signal.correlate(sig_orig, sig_rec)) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() corr_path = (logging_path + "/" + dt + "_tx_rx_corr.svg") plt.plot(c, label="corr") @@ -107,7 +110,7 @@ class Dab_Util: Returns an aligned version of sig_tx and sig_rx by cropping and subsample alignment """ - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_sync_raw.svg" @@ -151,7 +154,7 @@ class Dab_Util: sig_tx = sig_tx[:-1] sig_rx = sig_rx[:-1] - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_sync_sample_aligned.svg" @@ -175,7 +178,7 @@ class Dab_Util: sig_rx = sa.subsample_align(sig_rx, sig_tx) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_sync_subsample_aligned.svg" @@ -199,7 +202,7 @@ class Dab_Util: sig_rx = pa.phase_align(sig_rx, sig_tx) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_sync_phase_aligned.svg" diff --git a/dpd/src/ExtractStatistic.py b/dpd/src/ExtractStatistic.py index d27cd77..e917909 100644 --- a/dpd/src/ExtractStatistic.py +++ b/dpd/src/ExtractStatistic.py @@ -12,8 +12,10 @@ import matplotlib.pyplot as plt import datetime import os import logging - -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None def _check_input_extract(tx_dpd, rx_received): @@ -64,7 +66,7 @@ class ExtractStatistic: self.plot = c.ES_plot def _plot_and_log(self, tx_values, rx_values, phase_diffs_values, phase_diffs_values_lists): - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_ExtractStatistic.png" diff --git a/dpd/src/MER.py b/dpd/src/MER.py index f186261..a4c3591 100644 --- a/dpd/src/MER.py +++ b/dpd/src/MER.py @@ -11,7 +11,7 @@ import logging try: logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) except: - logging_path = "/tmp/" + logging_path = None import numpy as np import matplotlib @@ -76,9 +76,11 @@ class MER: spectrum = self._calc_spectrum(tx) - if self.plot: + if self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_MER" + debug_name + ".svg" + else: + fig_path = None MERs = [] for i, (x, y) in enumerate(self._split_in_carrier( @@ -103,7 +105,7 @@ class MER: ylim = ax.get_ylim() ax.set_ylim(ylim[0] - (ylim[1] - ylim[0]) * 0.1, ylim[1]) - if self.plot: + if fig_path is not None: plt.tight_layout() plt.savefig(fig_path) plt.show() diff --git a/dpd/src/Measure.py b/dpd/src/Measure.py index d4b1d9e..e4333d9 100644 --- a/dpd/src/Measure.py +++ b/dpd/src/Measure.py @@ -11,9 +11,7 @@ import struct import numpy as np import src.Dab_Util as DU import os - import logging -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) class Measure: """Collect Measurement from DabMod""" diff --git a/dpd/src/Measure_Shoulders.py b/dpd/src/Measure_Shoulders.py index c733dfd..2249ac6 100644 --- a/dpd/src/Measure_Shoulders.py +++ b/dpd/src/Measure_Shoulders.py @@ -10,7 +10,10 @@ import os import logging import multiprocessing -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np import matplotlib.pyplot as plt @@ -79,6 +82,9 @@ class Measure_Shoulders: self.plot = c.MS_plot def _plot(self, signal): + if logging_path is None: + return + dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_sync_subsample_aligned.svg" diff --git a/dpd/src/Model.py b/dpd/src/Model.py index 67feeb6..b2c303f 100644 --- a/dpd/src/Model.py +++ b/dpd/src/Model.py @@ -2,6 +2,12 @@ from src.Model_Poly import Poly from src.Model_Lut import Lut +def select_model_from_dpddata(dpddata): + if dpddata[0] == 'lut': + return Lut + elif dpddata[0] == 'poly': + return Poly + # The MIT License (MIT) # # Copyright (c) 2017 Andreas Steger diff --git a/dpd/src/Model_AM.py b/dpd/src/Model_AM.py index d7e880c..596ca4a 100644 --- a/dpd/src/Model_AM.py +++ b/dpd/src/Model_AM.py @@ -8,8 +8,10 @@ import datetime import os import logging - -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np import matplotlib.pyplot as plt @@ -55,7 +57,7 @@ class Model_AM: self.plot = plot def _plot(self, tx_dpd, rx_received, coefs_am, coefs_am_new): - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: tx_range, rx_est = calc_line(coefs_am, 0, 0.6) tx_range_new, rx_est_new = calc_line(coefs_am_new, 0, 0.6) diff --git a/dpd/src/Model_Lut.py b/dpd/src/Model_Lut.py index 6d4db52..b349433 100644 --- a/dpd/src/Model_Lut.py +++ b/dpd/src/Model_Lut.py @@ -7,8 +7,10 @@ import os import logging - -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np diff --git a/dpd/src/Model_PM.py b/dpd/src/Model_PM.py index d4f8c00..e721d1a 100644 --- a/dpd/src/Model_PM.py +++ b/dpd/src/Model_PM.py @@ -8,8 +8,10 @@ import datetime import os import logging - -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np import matplotlib.pyplot as plt @@ -41,7 +43,7 @@ class Model_PM: self.plot = plot def _plot(self, tx_dpd, phase_diff, coefs_pm, coefs_pm_new): - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: tx_range, phase_diff_est = self.calc_line(coefs_pm, 0, 0.6) tx_range_new, phase_diff_est_new = self.calc_line(coefs_pm_new, 0, 0.6) diff --git a/dpd/src/Model_Poly.py b/dpd/src/Model_Poly.py index ff15941..1cf8ecd 100644 --- a/dpd/src/Model_Poly.py +++ b/dpd/src/Model_Poly.py @@ -7,8 +7,10 @@ import os import logging - -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np diff --git a/dpd/src/RX_Agc.py b/dpd/src/RX_Agc.py index 670fbbb..7b5e0b6 100644 --- a/dpd/src/RX_Agc.py +++ b/dpd/src/RX_Agc.py @@ -9,7 +9,10 @@ import datetime import os import logging import time -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np import matplotlib @@ -70,6 +73,9 @@ class Agc: def plot_estimates(self): """Plots the estimate of for Max, Median, Mean for different number of samples.""" + if logging_path is None: + return + self.adapt.set_rxgain(self.min_rxgain) time.sleep(1) diff --git a/dpd/src/Symbol_align.py b/dpd/src/Symbol_align.py index d921f25..f2802ee 100644 --- a/dpd/src/Symbol_align.py +++ b/dpd/src/Symbol_align.py @@ -12,7 +12,7 @@ import logging try: logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) except: - logging_path = "/tmp/" + logging_path = None import numpy as np import scipy @@ -75,7 +75,7 @@ class Symbol_align: offset = peaks[np.argmin([tx_product_avg[peak] for peak in peaks])] - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_Symbol_align.svg" diff --git a/dpd/src/TX_Agc.py b/dpd/src/TX_Agc.py index 3c804fa..7555450 100644 --- a/dpd/src/TX_Agc.py +++ b/dpd/src/TX_Agc.py @@ -10,7 +10,10 @@ import os import logging import time -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np import matplotlib diff --git a/dpd/src/phase_align.py b/dpd/src/phase_align.py index 68c216d..21a210c 100644 --- a/dpd/src/phase_align.py +++ b/dpd/src/phase_align.py @@ -7,7 +7,10 @@ import datetime import os import logging -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np import matplotlib.pyplot as plt @@ -24,7 +27,7 @@ def phase_align(sig, ref_sig, plot=False): real_diffs = np.cos(angle_diff) imag_diffs = np.sin(angle_diff) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and plot: + if logging.getLogger().getEffectiveLevel() == logging.DEBUG and plot and logging_path is not None: dt = datetime.datetime.now().isoformat() fig_path = logging_path + "/" + dt + "_phase_align.svg" diff --git a/dpd/src/subsample_align.py b/dpd/src/subsample_align.py index 68f3591..a5e9f8c 100755 --- a/dpd/src/subsample_align.py +++ b/dpd/src/subsample_align.py @@ -7,8 +7,10 @@ import datetime import logging import os - -logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +try: + logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) +except AttributeError: + logging_path = None import numpy as np from scipy import optimize @@ -72,7 +74,7 @@ def subsample_align(sig, ref_sig, plot=False): if optim_result.success: best_tau = optim_result.x - if plot: + if plot and logging_path is not None: corr = np.vectorize(correlate_for_delay) ixs = np.linspace(-1, 1, 100) taus = corr(ixs) -- cgit v1.2.3 From 740d4815fda8737cc7f021999d30aeacd851b032 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 29 Dec 2017 07:40:20 +0100 Subject: DPDCE: fix Adapt init and pickle usage --- dpd/apply_adapt_dumps.py | 2 +- dpd/src/Adapt.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'dpd/src') diff --git a/dpd/apply_adapt_dumps.py b/dpd/apply_adapt_dumps.py index f1f3359..0eb65f3 100755 --- a/dpd/apply_adapt_dumps.py +++ b/dpd/apply_adapt_dumps.py @@ -49,7 +49,7 @@ port_rc = cli_args.rc_port coef_path = cli_args.coefs filename = cli_args.file -adapt = Adapt(port_rc, coef_path) +adapt = Adapt.Adapt(port_rc, coef_path) print("Loading and applying DPD settings from {}".format(filename)) adapt.load(filename) diff --git a/dpd/src/Adapt.py b/dpd/src/Adapt.py index c78c920..939e50e 100644 --- a/dpd/src/Adapt.py +++ b/dpd/src/Adapt.py @@ -239,20 +239,20 @@ class Adapt: "digital_gain": self.get_digital_gain(), "predistorter": self.get_predistorter() } - with open(path, "w") as f: + with open(path, "wb") as f: pickle.dump(d, f) return path def load(self, path): """Restore settings from a file""" - with open(path, "r") as f: + with open(path, "rb") as f: d = pickle.load(f) - self.set_txgain(d["txgain"]) - self.set_digital_gain(d["digital_gain"]) - self.set_rxgain(d["rxgain"]) - self.set_predistorter(d["predistorter"]) + self.set_txgain(d["txgain"]) + self.set_digital_gain(d["digital_gain"]) + self.set_rxgain(d["rxgain"]) + self.set_predistorter(d["predistorter"]) # The MIT License (MIT) # -- cgit v1.2.3 From bc25ed90fb34398f9fd3066b7237d1306628b16f Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 29 Dec 2017 08:32:58 +0100 Subject: Transform Const into a global config structure, avoid depending on logging for plot location --- dpd/apply_adapt_dumps.py | 21 ++++----- dpd/main.py | 10 ++-- dpd/src/Adapt.py | 14 ++---- dpd/src/Const.py | 106 ------------------------------------------ dpd/src/Dab_Util.py | 29 +++++------- dpd/src/ExtractStatistic.py | 10 +--- dpd/src/GlobalConfig.py | 107 +++++++++++++++++++++++++++++++++++++++++++ dpd/src/MER.py | 9 +--- dpd/src/Measure.py | 5 +- dpd/src/Measure_Shoulders.py | 10 +--- dpd/src/Model_AM.py | 9 +--- dpd/src/Model_Lut.py | 6 --- dpd/src/Model_PM.py | 9 +--- dpd/src/Model_Poly.py | 7 --- dpd/src/RX_Agc.py | 9 +--- dpd/src/Symbol_align.py | 10 +--- dpd/src/TX_Agc.py | 6 --- dpd/src/phase_align.py | 9 +--- dpd/src/subsample_align.py | 12 ++--- 19 files changed, 160 insertions(+), 238 deletions(-) delete mode 100644 dpd/src/Const.py create mode 100644 dpd/src/GlobalConfig.py (limited to 'dpd/src') diff --git a/dpd/apply_adapt_dumps.py b/dpd/apply_adapt_dumps.py index 0eb65f3..20bc013 100755 --- a/dpd/apply_adapt_dumps.py +++ b/dpd/apply_adapt_dumps.py @@ -16,21 +16,11 @@ logging.basicConfig(format='%(asctime)s - %(module)s - %(levelname)s - %(message datefmt='%Y-%m-%d %H:%M:%S', level=logging.DEBUG) -import src.Measure as Measure -import src.Model as Model -import src.ExtractStatistic as ExtractStatistic import src.Adapt as Adapt -import src.RX_Agc as Agc -import src.TX_Agc as TX_Agc import argparse -import src.Const -import src.Symbol_align -import src.Measure_Shoulders -import src.MER - parser = argparse.ArgumentParser( - description="DPD Computation Engine for ODR-DabMod") + description="Load pkl dumps DPD settings into ODR-DabMod") parser.add_argument('--port', default=50055, type=int, help='port of DPD server to connect to (default: 50055)', required=False) @@ -49,7 +39,14 @@ port_rc = cli_args.rc_port coef_path = cli_args.coefs filename = cli_args.file -adapt = Adapt.Adapt(port_rc, coef_path) +# No need to initialise a GlobalConfig since adapt only needs this one field +class DummyConfig: + def __init__(self): + self.plot_location = None + +c = DummyConfig() + +adapt = Adapt.Adapt(c, port_rc, coef_path) print("Loading and applying DPD settings from {}".format(filename)) adapt.load(filename) diff --git a/dpd/main.py b/dpd/main.py index e15c6b5..24daa5a 100755 --- a/dpd/main.py +++ b/dpd/main.py @@ -58,7 +58,7 @@ parser.add_argument('-L', '--lut', help='Use lookup table instead of polynomial predistorter', action="store_true") parser.add_argument('--plot', - help='Enable all plots, to be more selective choose plots in Const.py', + help='Enable all plots, to be more selective choose plots in GlobalConfig.py', action="store_true") parser.add_argument('--name', default="", type=str, help='Name of the logging directory') @@ -113,17 +113,17 @@ from src.Adapt import Adapt from src.RX_Agc import Agc from src.TX_Agc import TX_Agc from src.Symbol_align import Symbol_align -from src.Const import Const +from src.GlobalConfig import GlobalConfig from src.MER import MER from src.Measure_Shoulders import Measure_Shoulders -c = Const(samplerate, target_median, plot) +c = GlobalConfig(cli_args, logging_path) SA = Symbol_align(c) MER = MER(c) MS = Measure_Shoulders(c) -meas = Measure(samplerate, port, num_req) +meas = Measure(c, samplerate, port, num_req) extStat = ExtractStatistic(c) -adapt = Adapt(port_rc, coef_path) +adapt = Adapt(c, port_rc, coef_path) if cli_args.lut: model = Lut(c) diff --git a/dpd/src/Adapt.py b/dpd/src/Adapt.py index 939e50e..153442b 100644 --- a/dpd/src/Adapt.py +++ b/dpd/src/Adapt.py @@ -16,11 +16,6 @@ import os import datetime import pickle -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - LUT_LEN = 32 FORMAT_POLY = 1 FORMAT_LUT = 2 @@ -58,8 +53,9 @@ class Adapt: ZMQ remote control. """ - def __init__(self, port, coef_path): + def __init__(self, config, port, coef_path): logging.debug("Instantiate Adapt object") + self.c = config self.port = port self.coef_path = coef_path self.host = "localhost" @@ -229,10 +225,10 @@ class Adapt: """Backup current settings to a file""" dt = datetime.datetime.now().isoformat() if path is None: - if logging_path is not None: - path = logging_path + "/" + dt + "_adapt.pkl" + if self.c.plot_location is not None: + path = self.c.plot_location + "/" + dt + "_adapt.pkl" else: - raise Exception("Cannot dump Adapt without either logging_path or path set") + raise Exception("Cannot dump Adapt without either plot_location or path set") d = { "txgain": self.get_txgain(), "rxgain": self.get_rxgain(), diff --git a/dpd/src/Const.py b/dpd/src/Const.py deleted file mode 100644 index d80cfac..0000000 --- a/dpd/src/Const.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -# -# DPD Computation Engine, constants. -# -# Source for DAB standard: etsi_EN_300_401_v010401p p145 -# -# http://www.opendigitalradio.org -# Licence: The MIT License, see notice at the end of this file - -import numpy as np - - -class Const: - def __init__(self, sample_rate, target_median, plot): - assert sample_rate == 8192000 # By now only constants for 8192000 - self.sample_rate = sample_rate - - # DAB frame - # Time domain - self.T_F = sample_rate / 2048000 * 196608 # Transmission frame duration - self.T_NULL = sample_rate / 2048000 * 2656 # Null symbol duration - self.T_S = sample_rate / 2048000 * 2552 # Duration of OFDM symbols of indices l = 1, 2, 3,... L; - self.T_U = sample_rate / 2048000 * 2048 # Inverse of carrier spacing - self.T_C = sample_rate / 2048000 * 504 # Duration of cyclic prefix - - # Frequency Domain - # example: np.delete(fft[3328:4865], 768) - self.FFT_delta = 1536 # Number of carrier frequencies - self.FFT_delete = 768 - self.FFT_start = 3328 - self.FFT_end = 4865 - - # Calculate sample offset from phase rotation - # time per sample = 1 / sample_rate - # frequency per bin = 1kHz - # phase difference per sample offset = delta_t * 2 * pi * delta_freq - self.phase_offset_per_sample = 1. / sample_rate * 2 * np.pi * 1000 - - # Constants for ExtractStatistic - self.ES_plot = plot - self.ES_start = 0.0 - self.ES_end = 1.0 - self.ES_n_bins = 64 # Number of bins between ES_start and ES_end - self.ES_n_per_bin = 128 # Number of measurements pre bin - - # Constants for Measure_Shoulder - self.MS_enable = False - self.MS_plot = plot - - meas_offset = 976 # Offset from center frequency to measure shoulder [kHz] - meas_width = 100 # Size of frequency delta to measure shoulder [kHz] - shoulder_offset_edge = np.abs(meas_offset - self.FFT_delta) - self.MS_shoulder_left_start = self.FFT_start - shoulder_offset_edge - meas_width / 2 - self.MS_shoulder_left_end = self.FFT_start - shoulder_offset_edge + meas_width / 2 - self.MS_shoulder_right_start = self.FFT_end + shoulder_offset_edge - meas_width / 2 - self.MS_shoulder_right_end = self.FFT_end + shoulder_offset_edge + meas_width / 2 - self.MS_peak_start = self.FFT_start + 100 # Ignore region near edges - self.MS_peak_end = self.FFT_end - 100 - - self.MS_FFT_size = 8192 - self.MS_averaging_size = 4 * self.MS_FFT_size - self.MS_n_averaging = 40 - self.MS_n_proc = 4 - - # Constants for MER - self.MER_plot = plot - - # Constants for Model - self.MDL_plot = True or plot # Override default - - # Constants for Model_PM - # Set all phase offsets to zero for TX amplitude < MPM_tx_min - self.MPM_tx_min = 0.1 - - # Constants for TX_Agc - self.TAGC_max_txgain = 89 # USRP B200 specific - self.TAGC_tx_median_target = target_median - self.TAGC_tx_median_max = self.TAGC_tx_median_target * 1.4 - self.TAGC_tx_median_min = self.TAGC_tx_median_target / 1.4 - - # Constants for RX_AGC - self.RAGC_min_rxgain = 25 # USRP B200 specific - self.RAGC_rx_median_target = target_median - -# The MIT License (MIT) -# -# Copyright (c) 2017 Andreas Steger -# Copyright (c) 2017 Matthias P. Braendli -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. diff --git a/dpd/src/Dab_Util.py b/dpd/src/Dab_Util.py index 56c9503..bc89a39 100644 --- a/dpd/src/Dab_Util.py +++ b/dpd/src/Dab_Util.py @@ -8,12 +8,6 @@ import datetime import os import logging - -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import matplotlib @@ -36,10 +30,11 @@ class Dab_Util: complex IQ samples of a DAB signal """ - def __init__(self, sample_rate, plot=False): + def __init__(self, config, sample_rate, plot=False): """ :param sample_rate: sample rate [sample/sec] to use for calculations """ + self.c = config self.sample_rate = sample_rate self.dab_bandwidth = 1536000 # Bandwidth of a dab signal self.frame_ms = 96 # Duration of a Dab frame @@ -56,9 +51,9 @@ class Dab_Util: off = sig_rec.shape[0] c = np.abs(signal.correlate(sig_orig, sig_rec)) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - corr_path = (logging_path + "/" + dt + "_tx_rx_corr.svg") + corr_path = self.c.plot_location + "/" + dt + "_tx_rx_corr.png" plt.plot(c, label="corr") plt.legend() plt.savefig(corr_path) @@ -110,9 +105,9 @@ class Dab_Util: Returns an aligned version of sig_tx and sig_rx by cropping and subsample alignment """ - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_sync_raw.svg" + fig_path = self.c.plot_location + "/" + dt + "_sync_raw.png" fig, axs = plt.subplots(2) axs[0].plot(np.abs(sig_tx[:128]), label="TX Frame") @@ -154,9 +149,9 @@ class Dab_Util: sig_tx = sig_tx[:-1] sig_rx = sig_rx[:-1] - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_sync_sample_aligned.svg" + fig_path = self.c.plot_location + "/" + dt + "_sync_sample_aligned.png" fig, axs = plt.subplots(2) axs[0].plot(np.abs(sig_tx[:128]), label="TX Frame") @@ -178,9 +173,9 @@ class Dab_Util: sig_rx = sa.subsample_align(sig_rx, sig_tx) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_sync_subsample_aligned.svg" + fig_path = self.c.plot_location + "/" + dt + "_sync_subsample_aligned.png" fig, axs = plt.subplots(2) axs[0].plot(np.abs(sig_tx[:128]), label="TX Frame") @@ -202,9 +197,9 @@ class Dab_Util: sig_rx = pa.phase_align(sig_rx, sig_tx) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_sync_phase_aligned.svg" + fig_path = self.c.plot_location + "/" + dt + "_sync_phase_aligned.png" fig, axs = plt.subplots(2) axs[0].plot(np.abs(sig_tx[:128]), label="TX Frame") diff --git a/dpd/src/ExtractStatistic.py b/dpd/src/ExtractStatistic.py index e917909..639513a 100644 --- a/dpd/src/ExtractStatistic.py +++ b/dpd/src/ExtractStatistic.py @@ -8,14 +8,9 @@ import numpy as np import matplotlib.pyplot as plt - import datetime import os import logging -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None def _check_input_extract(tx_dpd, rx_received): @@ -66,10 +61,9 @@ class ExtractStatistic: self.plot = c.ES_plot def _plot_and_log(self, tx_values, rx_values, phase_diffs_values, phase_diffs_values_lists): - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: - + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_ExtractStatistic.png" + fig_path = self.c.plot_location + "/" + dt + "_ExtractStatistic.png" sub_rows = 3 sub_cols = 1 fig = plt.figure(figsize=(sub_cols * 6, sub_rows / 2. * 6)) diff --git a/dpd/src/GlobalConfig.py b/dpd/src/GlobalConfig.py new file mode 100644 index 0000000..684a881 --- /dev/null +++ b/dpd/src/GlobalConfig.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +# +# DPD Computation Engine, constants and global configuration +# +# Source for DAB standard: etsi_EN_300_401_v010401p p145 +# +# http://www.opendigitalradio.org +# Licence: The MIT License, see notice at the end of this file + +import numpy as np + +class GlobalConfig: + def __init__(self, cli_args, plot_location): + self.sample_rate = cli_args.sample_rate + assert self.sample_rate == 8192000 # By now only constants for 8192000 + + self.plot_location = plot_location + + # DAB frame + # Time domain + self.T_F = self.sample_rate / 2048000 * 196608 # Transmission frame duration + self.T_NULL = self.sample_rate / 2048000 * 2656 # Null symbol duration + self.T_S = self.sample_rate / 2048000 * 2552 # Duration of OFDM symbols of indices l = 1, 2, 3,... L; + self.T_U = self.sample_rate / 2048000 * 2048 # Inverse of carrier spacing + self.T_C = self.sample_rate / 2048000 * 504 # Duration of cyclic prefix + + # Frequency Domain + # example: np.delete(fft[3328:4865], 768) + self.FFT_delta = 1536 # Number of carrier frequencies + self.FFT_delete = 768 + self.FFT_start = 3328 + self.FFT_end = 4865 + + # Calculate sample offset from phase rotation + # time per sample = 1 / sample_rate + # frequency per bin = 1kHz + # phase difference per sample offset = delta_t * 2 * pi * delta_freq + self.phase_offset_per_sample = 1. / self.sample_rate * 2 * np.pi * 1000 + + # Constants for ExtractStatistic + self.ES_plot = cli_args.plot + self.ES_start = 0.0 + self.ES_end = 1.0 + self.ES_n_bins = 64 # Number of bins between ES_start and ES_end + self.ES_n_per_bin = 128 # Number of measurements pre bin + + # Constants for Measure_Shoulder + self.MS_enable = False + self.MS_plot = cli_args.plot + + meas_offset = 976 # Offset from center frequency to measure shoulder [kHz] + meas_width = 100 # Size of frequency delta to measure shoulder [kHz] + shoulder_offset_edge = np.abs(meas_offset - self.FFT_delta) + self.MS_shoulder_left_start = self.FFT_start - shoulder_offset_edge - meas_width / 2 + self.MS_shoulder_left_end = self.FFT_start - shoulder_offset_edge + meas_width / 2 + self.MS_shoulder_right_start = self.FFT_end + shoulder_offset_edge - meas_width / 2 + self.MS_shoulder_right_end = self.FFT_end + shoulder_offset_edge + meas_width / 2 + self.MS_peak_start = self.FFT_start + 100 # Ignore region near edges + self.MS_peak_end = self.FFT_end - 100 + + self.MS_FFT_size = 8192 + self.MS_averaging_size = 4 * self.MS_FFT_size + self.MS_n_averaging = 40 + self.MS_n_proc = 4 + + # Constants for MER + self.MER_plot = cli_args.plot + + # Constants for Model + self.MDL_plot = cli_args.plot + + # Constants for Model_PM + # Set all phase offsets to zero for TX amplitude < MPM_tx_min + self.MPM_tx_min = 0.1 + + # Constants for TX_Agc + self.TAGC_max_txgain = 89 # USRP B200 specific + self.TAGC_tx_median_target = cli_args.target_median + self.TAGC_tx_median_max = self.TAGC_tx_median_target * 1.4 + self.TAGC_tx_median_min = self.TAGC_tx_median_target / 1.4 + + # Constants for RX_AGC + self.RAGC_min_rxgain = 25 # USRP B200 specific + self.RAGC_rx_median_target = cli_args.target_median + +# The MIT License (MIT) +# +# Copyright (c) 2017 Andreas Steger +# Copyright (c) 2017 Matthias P. Braendli +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. diff --git a/dpd/src/MER.py b/dpd/src/MER.py index a4c3591..693058d 100644 --- a/dpd/src/MER.py +++ b/dpd/src/MER.py @@ -8,11 +8,6 @@ import datetime import os import logging -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except: - logging_path = None - import numpy as np import matplotlib matplotlib.use('agg') @@ -76,9 +71,9 @@ class MER: spectrum = self._calc_spectrum(tx) - if self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_MER" + debug_name + ".svg" + fig_path = self.c.plot_location + "/" + dt + "_MER" + debug_name + ".png" else: fig_path = None diff --git a/dpd/src/Measure.py b/dpd/src/Measure.py index e4333d9..b7423c6 100644 --- a/dpd/src/Measure.py +++ b/dpd/src/Measure.py @@ -15,8 +15,9 @@ import logging class Measure: """Collect Measurement from DabMod""" - def __init__(self, samplerate, port, num_samples_to_request): + def __init__(self, config, samplerate, port, num_samples_to_request): logging.info("Instantiate Measure object") + self.c = config self.samplerate = samplerate self.sizeof_sample = 8 # complex floats self.port = port @@ -104,7 +105,7 @@ class Measure: rx_median = np.median(np.abs(rxframe)) rxframe = rxframe / rx_median * np.median(np.abs(txframe)) - du = DU.Dab_Util(self.samplerate) + du = DU.Dab_Util(self.c, self.samplerate) txframe_aligned, rxframe_aligned = du.subsample_align(txframe, rxframe) logging.info( diff --git a/dpd/src/Measure_Shoulders.py b/dpd/src/Measure_Shoulders.py index 2249ac6..fd90050 100644 --- a/dpd/src/Measure_Shoulders.py +++ b/dpd/src/Measure_Shoulders.py @@ -9,12 +9,6 @@ import datetime import os import logging import multiprocessing - -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import matplotlib.pyplot as plt @@ -82,11 +76,11 @@ class Measure_Shoulders: self.plot = c.MS_plot def _plot(self, signal): - if logging_path is None: + if self.c.plot_location is None: return dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_sync_subsample_aligned.svg" + fig_path = self.c.plot_location + "/" + dt + "_sync_subsample_aligned.png" fft = calc_fft_db(signal, 100, self.c) peak, idxs_peak = _calc_peak(fft, self.c) diff --git a/dpd/src/Model_AM.py b/dpd/src/Model_AM.py index 596ca4a..9800d83 100644 --- a/dpd/src/Model_AM.py +++ b/dpd/src/Model_AM.py @@ -8,11 +8,6 @@ import datetime import os import logging -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import matplotlib.pyplot as plt @@ -57,12 +52,12 @@ class Model_AM: self.plot = plot def _plot(self, tx_dpd, rx_received, coefs_am, coefs_am_new): - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: tx_range, rx_est = calc_line(coefs_am, 0, 0.6) tx_range_new, rx_est_new = calc_line(coefs_am_new, 0, 0.6) dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_Model_AM.svg" + fig_path = self.c.plot_location + "/" + dt + "_Model_AM.png" sub_rows = 1 sub_cols = 1 fig = plt.figure(figsize=(sub_cols * 6, sub_rows / 2. * 6)) diff --git a/dpd/src/Model_Lut.py b/dpd/src/Model_Lut.py index b349433..e70fdb0 100644 --- a/dpd/src/Model_Lut.py +++ b/dpd/src/Model_Lut.py @@ -7,14 +7,8 @@ import os import logging -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np - class Lut: """Implements a model that calculates lookup table coefficients""" diff --git a/dpd/src/Model_PM.py b/dpd/src/Model_PM.py index e721d1a..3aafea0 100644 --- a/dpd/src/Model_PM.py +++ b/dpd/src/Model_PM.py @@ -8,11 +8,6 @@ import datetime import os import logging -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import matplotlib.pyplot as plt @@ -43,12 +38,12 @@ class Model_PM: self.plot = plot def _plot(self, tx_dpd, phase_diff, coefs_pm, coefs_pm_new): - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: tx_range, phase_diff_est = self.calc_line(coefs_pm, 0, 0.6) tx_range_new, phase_diff_est_new = self.calc_line(coefs_pm_new, 0, 0.6) dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_Model_PM.svg" + fig_path = self.c.plot_location + "/" + dt + "_Model_PM.png" sub_rows = 1 sub_cols = 1 fig = plt.figure(figsize=(sub_cols * 6, sub_rows / 2. * 6)) diff --git a/dpd/src/Model_Poly.py b/dpd/src/Model_Poly.py index 1cf8ecd..3ec717b 100644 --- a/dpd/src/Model_Poly.py +++ b/dpd/src/Model_Poly.py @@ -7,11 +7,6 @@ import os import logging -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import src.Model_AM as Model_AM @@ -56,8 +51,6 @@ class Poly: self.model_am = Model_AM.Model_AM(c, plot=self.plot) self.model_pm = Model_PM.Model_PM(c, plot=self.plot) - self.plot = c.MDL_plot - def reset_coefs(self): self.coefs_am = np.zeros(5, dtype=np.float32) self.coefs_am[0] = 1 diff --git a/dpd/src/RX_Agc.py b/dpd/src/RX_Agc.py index 7b5e0b6..f778dee 100644 --- a/dpd/src/RX_Agc.py +++ b/dpd/src/RX_Agc.py @@ -9,11 +9,6 @@ import datetime import os import logging import time -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import matplotlib matplotlib.use('agg') @@ -73,14 +68,14 @@ class Agc: def plot_estimates(self): """Plots the estimate of for Max, Median, Mean for different number of samples.""" - if logging_path is None: + if self.c.plot_location is None: return self.adapt.set_rxgain(self.min_rxgain) time.sleep(1) dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_agc.svg" + fig_path = self.c.plot_location + "/" + dt + "_agc.png" fig, axs = plt.subplots(2, 2, figsize=(3*6,1*6)) axs = axs.ravel() diff --git a/dpd/src/Symbol_align.py b/dpd/src/Symbol_align.py index f2802ee..2a17a65 100644 --- a/dpd/src/Symbol_align.py +++ b/dpd/src/Symbol_align.py @@ -8,12 +8,6 @@ import datetime import os import logging - -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except: - logging_path = None - import numpy as np import scipy import matplotlib @@ -75,9 +69,9 @@ class Symbol_align: offset = peaks[np.argmin([tx_product_avg[peak] for peak in peaks])] - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and self.plot and logging_path is not None: + if self.plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_Symbol_align.svg" + fig_path = self.c.plot_location + "/" + dt + "_Symbol_align.png" fig = plt.figure(figsize=(9, 9)) diff --git a/dpd/src/TX_Agc.py b/dpd/src/TX_Agc.py index 7555450..309193d 100644 --- a/dpd/src/TX_Agc.py +++ b/dpd/src/TX_Agc.py @@ -9,12 +9,6 @@ import datetime import os import logging import time - -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import matplotlib diff --git a/dpd/src/phase_align.py b/dpd/src/phase_align.py index 21a210c..8654333 100644 --- a/dpd/src/phase_align.py +++ b/dpd/src/phase_align.py @@ -7,11 +7,6 @@ import datetime import os import logging -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np import matplotlib.pyplot as plt @@ -27,9 +22,9 @@ def phase_align(sig, ref_sig, plot=False): real_diffs = np.cos(angle_diff) imag_diffs = np.sin(angle_diff) - if logging.getLogger().getEffectiveLevel() == logging.DEBUG and plot and logging_path is not None: + if plot and self.c.plot_location is not None: dt = datetime.datetime.now().isoformat() - fig_path = logging_path + "/" + dt + "_phase_align.svg" + fig_path = self.c.plot_location + "/" + dt + "_phase_align.png" plt.subplot(511) plt.hist(angle_diff, bins=60, label="Angle Diff") diff --git a/dpd/src/subsample_align.py b/dpd/src/subsample_align.py index a5e9f8c..20ae56b 100755 --- a/dpd/src/subsample_align.py +++ b/dpd/src/subsample_align.py @@ -7,16 +7,10 @@ import datetime import logging import os -try: - logging_path = os.path.dirname(logging.getLoggerClass().root.handlers[0].baseFilename) -except AttributeError: - logging_path = None - import numpy as np from scipy import optimize import matplotlib.pyplot as plt - def gen_omega(length): if (length % 2) == 1: raise ValueError("Needs an even length array.") @@ -34,7 +28,7 @@ def gen_omega(length): return omega -def subsample_align(sig, ref_sig, plot=False): +def subsample_align(sig, ref_sig, plot_location=None): """Do subsample alignment for sig relative to the reference signal ref_sig. The delay between the two must be less than sample @@ -74,13 +68,13 @@ def subsample_align(sig, ref_sig, plot=False): if optim_result.success: best_tau = optim_result.x - if plot and logging_path is not None: + if plot_location is not None: corr = np.vectorize(correlate_for_delay) ixs = np.linspace(-1, 1, 100) taus = corr(ixs) dt = datetime.datetime.now().isoformat() - tau_path = (logging_path + "/" + dt + "_tau.svg") + tau_path = (plot_location + "/" + dt + "_tau.png") plt.plot(ixs, taus) plt.title("Subsample correlation, minimum is best: {}".format(best_tau)) plt.savefig(tau_path) -- cgit v1.2.3 From 1a3ae6085967be4cd76cabb2a630a04464f38748 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 29 Dec 2017 08:42:10 +0100 Subject: DPDCE: Add reset option --- dpd/main.py | 11 ++++++++++- dpd/src/GlobalConfig.py | 2 +- dpd/src/Model_Poly.py | 1 - 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'dpd/src') diff --git a/dpd/main.py b/dpd/main.py index 24daa5a..3ca0d35 100755 --- a/dpd/main.py +++ b/dpd/main.py @@ -11,6 +11,7 @@ This engine calculates and updates the parameter of the digital predistortion module of ODR-DabMod.""" +import sys import datetime import os import argparse @@ -62,6 +63,8 @@ parser.add_argument('--plot', action="store_true") parser.add_argument('--name', default="", type=str, help='Name of the logging directory') +parser.add_argument('-r', '--reset', action="store_true", + help='Reset the DPD settings to the defaults.') cli_args = parser.parse_args() @@ -101,7 +104,7 @@ console.setFormatter(formatter) # add the handler to the root logger logging.getLogger('').addHandler(console) -logging.info(cli_args) +logging.info("DPDCE starting up with options: {}".format(cli_args)) import numpy as np import traceback @@ -129,6 +132,8 @@ if cli_args.lut: model = Lut(c) else: model = Poly(c) + +# Models have the default settings on startup adapt.set_predistorter(model.get_dpd_data()) adapt.set_digital_gain(digital_gain) @@ -170,6 +175,10 @@ elif dpddata[0] == "lut": else: logging.error("Unknown dpd data format {}".format(dpddata[0])) +if cli_args.reset: + logging.info("DPD Settings were reset to default values.") + sys.exit(0) + tx_agc = TX_Agc(adapt, c) # Automatic Gain Control diff --git a/dpd/src/GlobalConfig.py b/dpd/src/GlobalConfig.py index 684a881..b84b9d7 100644 --- a/dpd/src/GlobalConfig.py +++ b/dpd/src/GlobalConfig.py @@ -11,7 +11,7 @@ import numpy as np class GlobalConfig: def __init__(self, cli_args, plot_location): - self.sample_rate = cli_args.sample_rate + self.sample_rate = cli_args.samplerate assert self.sample_rate == 8192000 # By now only constants for 8192000 self.plot_location = plot_location diff --git a/dpd/src/Model_Poly.py b/dpd/src/Model_Poly.py index 3ec717b..cdfd319 100644 --- a/dpd/src/Model_Poly.py +++ b/dpd/src/Model_Poly.py @@ -55,7 +55,6 @@ class Poly: self.coefs_am = np.zeros(5, dtype=np.float32) self.coefs_am[0] = 1 self.coefs_pm = np.zeros(5, dtype=np.float32) - return self.coefs_am, self.coefs_pm def train(self, tx_abs, rx_abs, phase_diff, lr=None): """ -- cgit v1.2.3 From a2df42ad09b27685d51d974ab86a306276f43a72 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 29 Dec 2017 09:04:49 +0100 Subject: DPDCE: Add status option --- dpd/main.py | 83 ++++++++++++++++++++++++++++++-------------------------- dpd/src/Adapt.py | 13 +++++++++ 2 files changed, 57 insertions(+), 39 deletions(-) (limited to 'dpd/src') diff --git a/dpd/main.py b/dpd/main.py index 3ca0d35..1a2d696 100755 --- a/dpd/main.py +++ b/dpd/main.py @@ -65,6 +65,8 @@ parser.add_argument('--name', default="", type=str, help='Name of the logging directory') parser.add_argument('-r', '--reset', action="store_true", help='Reset the DPD settings to the defaults.') +parser.add_argument('-s', '--status', action="store_true", + help='Display the currently running DPD settings.') cli_args = parser.parse_args() @@ -84,25 +86,34 @@ plot = cli_args.plot # Logging import logging -dt = datetime.datetime.now().isoformat() -logging_path = '/tmp/dpd_{}'.format(dt).replace('.', '_').replace(':', '-') -if name: - logging_path += '_' + name -os.makedirs(logging_path) -logging.basicConfig(format='%(asctime)s - %(module)s - %(levelname)s - %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', - filename='{}/dpd.log'.format(logging_path), - filemode='w', - level=logging.DEBUG) -# also log up to INFO to console -console = logging.StreamHandler() -console.setLevel(logging.INFO) -# set a format which is simpler for console use -formatter = logging.Formatter('%(asctime)s - %(module)s - %(levelname)s - %(message)s') -# tell the handler to use this format -console.setFormatter(formatter) -# add the handler to the root logger -logging.getLogger('').addHandler(console) +# Simple usage scenarios don't need to clutter /tmp +if not (cli_args.status or cli_args.reset): + dt = datetime.datetime.now().isoformat() + logging_path = '/tmp/dpd_{}'.format(dt).replace('.', '_').replace(':', '-') + if name: + logging_path += '_' + name + print("Logs and plots written to {}".format(logging_path)) + os.makedirs(logging_path) + logging.basicConfig(format='%(asctime)s - %(module)s - %(levelname)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + filename='{}/dpd.log'.format(logging_path), + filemode='w', + level=logging.DEBUG) + # also log up to INFO to console + console = logging.StreamHandler() + console.setLevel(logging.INFO) + # set a format which is simpler for console use + formatter = logging.Formatter('%(asctime)s - %(module)s - %(levelname)s - %(message)s') + # tell the handler to use this format + console.setFormatter(formatter) + # add the handler to the root logger + logging.getLogger('').addHandler(console) +else: + dt = datetime.datetime.now().isoformat() + logging.basicConfig(format='%(asctime)s - %(module)s - %(levelname)s - %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + level=logging.DEBUG) + logging_path = None logging.info("DPDCE starting up with options: {}".format(cli_args)) @@ -128,6 +139,17 @@ meas = Measure(c, samplerate, port, num_req) extStat = ExtractStatistic(c) adapt = Adapt(c, port_rc, coef_path) +if cli_args.status: + status = { + "txgain": adapt.get_txgain(), + "rxgain": adapt.get_rxgain(), + "digital_gain": adapt.get_digital_gain(), + "predistorter": adapt.get_predistorter() + } + + logging.info("ODR-DabMod currently running with {}".format(status)) + sys.exit(0) + if cli_args.lut: model = Lut(c) else: @@ -154,26 +176,9 @@ rx_gain = adapt.get_rxgain() digital_gain = adapt.get_digital_gain() dpddata = adapt.get_predistorter() -if dpddata[0] == "poly": - coefs_am = dpddata[1] - coefs_pm = dpddata[2] - logging.info( - "TX gain {}, RX gain {}, dpd_coefs_am {}," - " dpd_coefs_pm {}, digital_gain {}".format( - tx_gain, rx_gain, coefs_am, coefs_pm, digital_gain - ) - ) -elif dpddata[0] == "lut": - scalefactor = dpddata[1] - lut = dpddata[2] - logging.info( - "TX gain {}, RX gain {}, LUT scalefactor {}," - " LUT {}, digital_gain {}".format( - tx_gain, rx_gain, scalefactor, lut, digital_gain - ) - ) -else: - logging.error("Unknown dpd data format {}".format(dpddata[0])) + +logging.info("TX gain {}, RX gain {}, digital_gain {}, {!s}".format( + tx_gain, rx_gain, digital_gain, Adapt.dpddata_to_str(dpddata))) if cli_args.reset: logging.info("DPD Settings were reset to default values.") diff --git a/dpd/src/Adapt.py b/dpd/src/Adapt.py index 153442b..53ef037 100644 --- a/dpd/src/Adapt.py +++ b/dpd/src/Adapt.py @@ -42,6 +42,19 @@ def _write_lut_file(scalefactor, lut, path): f.write("{}\n{}\n".format(coef.real, coef.imag)) f.close() +def dpddata_to_str(dpddata): + if dpddata[0] == "poly": + coefs_am = dpddata[1] + coefs_pm = dpddata[2] + return "dpd_coefs_am {}, dpd_coefs_pm {}".format( + self.coefs_am, self.coefs_pm) + elif dpddata[0] == "lut": + scalefactor = dpddata[1] + lut = dpddata[2] + return "LUT scalefactor {}, LUT {}".format( + scalefactor, lut) + else: + raise ValueError("Unknown dpddata type {}".format(dpddata[0])) class Adapt: """Uses the ZMQ remote control to change parameters of the DabMod -- cgit v1.2.3 From 0386346f9bad5214b7515b33a1c8fac353de4b6b Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 29 Dec 2017 09:11:12 +0100 Subject: DPDCE fix dpddata_to_str() --- dpd/src/Adapt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dpd/src') diff --git a/dpd/src/Adapt.py b/dpd/src/Adapt.py index 53ef037..329ee20 100644 --- a/dpd/src/Adapt.py +++ b/dpd/src/Adapt.py @@ -47,7 +47,7 @@ def dpddata_to_str(dpddata): coefs_am = dpddata[1] coefs_pm = dpddata[2] return "dpd_coefs_am {}, dpd_coefs_pm {}".format( - self.coefs_am, self.coefs_pm) + coefs_am, coefs_pm) elif dpddata[0] == "lut": scalefactor = dpddata[1] lut = dpddata[2] -- cgit v1.2.3