diff options
-rw-r--r-- | dpd/README.md | 4 | ||||
-rwxr-xr-x | dpd/apply_adapt_dumps.py | 2 | ||||
-rw-r--r-- | dpd/environment.yml | 20 | ||||
-rwxr-xr-x | dpd/main.py | 114 | ||||
-rw-r--r-- | dpd/src/Const.py | 16 | ||||
-rw-r--r-- | dpd/src/ExtractStatistic.py | 6 | ||||
-rw-r--r-- | dpd/src/Heuristics.py | 4 | ||||
-rw-r--r-- | dpd/src/TX_Agc.py | 2 | ||||
-rw-r--r-- | dpd/src/Test_data.py | 2 |
9 files changed, 88 insertions, 82 deletions
diff --git a/dpd/README.md b/dpd/README.md index 77c53bd..4f92ecb 100644 --- a/dpd/README.md +++ b/dpd/README.md @@ -87,11 +87,11 @@ ODR-DabMod/odr-dabmod dpd/dpd.ini The script uses automatic gain control for both TX and RX gain, to get both a high quantization quality for the most frequent amplitude regions and a high enough back-off so the peaks are also quantized correctly. This means that the output power will stay at the same level, but the script may change TX gain to trade it with digital gain and also change RX gain. -As a first test you can run the main script without parameters. It preserves the output power and generates all available visualization plots in the newly created logging directory `/tmp/dpd_<time_stamp>`. As the script should increase the preak to shoulder ratio, tune the txgain in a way to be able to see a the change. For example to a ratio of -30dB. You can do this using the telnet remote control from `odr-dabmod`. To run it do following: +As a first test you can run the main script with the *--plot* parameter. It preserves the output power and generates all available visualization plots in the newly created logging directory `/tmp/dpd_<time_stamp>`. As the script should increase the preak to shoulder ratio, tune the txgain in a way to be able to see a the change. For example to a ratio of -30dB. You can do this using the telnet remote control from `odr-dabmod`. To run it do following: ``` cd dpd -python main.py +python main.py --plot ``` Each plot is stored to the logging directory under a filename containing its time stamp and its label. Following plots are generated chronologically: diff --git a/dpd/apply_adapt_dumps.py b/dpd/apply_adapt_dumps.py index 790a64a..4dac657 100755 --- a/dpd/apply_adapt_dumps.py +++ b/dpd/apply_adapt_dumps.py @@ -105,7 +105,7 @@ samplerate = cli_args.samplerate searchpath = cli_args.searchpath target_median = cli_args.target_median -c = src.Const.Const(samplerate, target_median, -1, -1, -1) +c = src.Const.Const(samplerate, target_median, False) SA = src.Symbol_align.Symbol_align(c) MER = src.MER.MER(c) MS = src.Measure_Shoulders.Measure_Shoulders(c) diff --git a/dpd/environment.yml b/dpd/environment.yml index 5c19258..8abedb2 100644 --- a/dpd/environment.yml +++ b/dpd/environment.yml @@ -1,5 +1,6 @@ name: dab channels: +- jochym - defaults dependencies: - _nb_ext_conf=0.4.0=py27_1 @@ -7,7 +8,7 @@ dependencies: - backports=1.0=py27_0 - backports_abc=0.5=py27_0 - bleach=1.5.0=py27_0 -- cairo=1.14.8=0 +- cairo=1.12.18=6 - clyent=1.2.2=py27_0 - configparser=3.5.0=py27_0 - cycler=0.10.0=py27_0 @@ -16,13 +17,14 @@ dependencies: - entrypoints=0.2.3=py27_0 - enum34=1.1.6=py27_0 - expat=2.1.0=0 -- fontconfig=2.12.1=3 +- fontconfig=2.11.1=6 - freetype=2.5.5=2 - functools32=3.2.3.2=py27_0 - get_terminal_size=1.0.0=py27_0 - glib=2.50.2=1 - gst-plugins-base=1.8.0=0 - gstreamer=1.8.0=0 +- harfbuzz=0.9.39=1 - html5lib=0.9999999=py27_0 - icu=54.1=0 - ipykernel=4.6.1=py27_0 @@ -30,7 +32,7 @@ dependencies: - ipython_genutils=0.2.0=py27_0 - ipywidgets=6.0.0=py27_0 - jinja2=2.9.6=py27_0 -- jpeg=9b=0 +- jpeg=8d=2 - jsonschema=2.6.0=py27_0 - jupyter=1.0.0=py27_3 - jupyter_client=5.1.0=py27_0 @@ -60,16 +62,18 @@ dependencies: - openssl=1.0.2k=2 - pandas=0.20.1=np112py27_0 - pandocfilters=1.4.1=py27_0 +- pango=1.39.0=0 - path.py=10.3.1=py27_0 - pathlib2=2.3.0=py27_0 - pcre=8.39=1 - pexpect=4.2.1=py27_0 - pickleshare=0.7.4=py27_0 - pip=9.0.1=py27_1 -- pixman=0.34.0=0 +- pixman=0.32.6=0 - plotly=2.0.9=py27_0 - prompt_toolkit=1.0.14=py27_0 - ptyprocess=0.5.2=py27_0 +- py2cairo=1.10.0=py27_2 - pycairo=1.10.0=py27_0 - pygments=2.2.0=py27_0 - pyparsing=2.1.4=py27_0 @@ -79,11 +83,12 @@ dependencies: - pytz=2017.2=py27_0 - pyyaml=3.12=py27_0 - pyzmq=16.0.2=py27_0 -- qt=5.6.2=4 +- qt=5.6.2=0 - qtconsole=4.3.0=py27_0 - readline=6.2=2 - requests=2.14.2=py27_0 - scandir=1.5=py27_0 +- scikit-learn=0.18.1=np112py27_1 - scipy=0.19.0=np112py27_0 - setuptools=27.2.0=py27_0 - simplegeneric=0.8.1=py27_1 @@ -105,6 +110,11 @@ dependencies: - yaml=0.1.6=0 - zeromq=4.1.5=0 - zlib=1.2.8=3 +- atk=2.8.0=0 +- gdk-pixbuf=2.28.2=0 +- gtk2=2.24.28=0 +- pygobject2=2.28.6=0 +- pygtk2=2.24.0=0 - pip: - backports-abc==0.5 - backports.shutil-get-terminal-size==1.0.0 diff --git a/dpd/main.py b/dpd/main.py index 5eaa81f..176f80f 100755 --- a/dpd/main.py +++ b/dpd/main.py @@ -12,45 +12,11 @@ predistortion module of ODR-DabMod.""" import datetime import os +import argparse import matplotlib matplotlib.use('GTKAgg') -import logging - -dt = datetime.datetime.now().isoformat() -logging_path = "/tmp/dpd_{}".format(dt).replace(".", "_").replace(":", "-") -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) - -import numpy as np -import traceback -import src.Measure as Measure -import src.Model as Model -import src.ExtractStatistic as ExtractStatistic -import src.Adapt as Adapt -import src.Agc as Agc -import src.TX_Agc as TX_Agc -from src.Symbol_align import Symbol_align -from src.Const import Const -from src.MER import MER -from src.Measure_Shoulders import Measure_Shoulders -import argparse -import src.Heuristics as Heur parser = argparse.ArgumentParser( description="DPD Computation Engine for ODR-DabMod") @@ -91,16 +57,13 @@ parser.add_argument('-i', '--iterations', default=1, type=int, parser.add_argument('-L', '--lut', help='Use lookup table instead of polynomial predistorter', action="store_true") -parser.add_argument('--n_bins', default='64', type=int, - required=False) -parser.add_argument('--n_per_bin', default='128', type=int, - required=False) -parser.add_argument('--n_meas', default='20', type=int, - help='Number of samples to request from ODR-DabMod', - required=False) +parser.add_argument('--plot', + help='Enable all plots, to be more selective choose plots in Const.py', + action="store_true") +parser.add_argument('--name', default="", type=str, + help='Name of the logging directory') cli_args = parser.parse_args() -logging.info(cli_args) port = cli_args.port port_rc = cli_args.rc_port @@ -112,24 +75,59 @@ num_iter = cli_args.iterations target_median = cli_args.target_median rxgain = cli_args.rxgain txgain = cli_args.txgain +name = cli_args.name +plot = cli_args.plot -n_bins = cli_args.n_bins -n_per_bin = cli_args.n_per_bin -n_meas = cli_args.n_meas +# Logging +import logging -c = Const(samplerate, target_median, n_bins, n_per_bin, n_meas) +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) + +logging.info(cli_args) + +import numpy as np +import traceback +from src.Model import Lut, Poly +import src.Heuristics as Heuristics +from src.Measure import Measure +from src.ExtractStatistic import ExtractStatistic +from src.Adapt import Adapt +from src.Agc import Agc +from src.TX_Agc import TX_Agc +from src.Symbol_align import Symbol_align +from src.Const import Const +from src.MER import MER +from src.Measure_Shoulders import Measure_Shoulders + +c = Const(samplerate, target_median, plot) SA = Symbol_align(c) MER = MER(c) MS = Measure_Shoulders(c) - -meas = Measure.Measure(samplerate, port, num_req) -extStat = ExtractStatistic.ExtractStatistic(c) -adapt = Adapt.Adapt(port_rc, coef_path) +meas = Measure(samplerate, port, num_req) +extStat = ExtractStatistic(c) +adapt = Adapt(port_rc, coef_path) if cli_args.lut: - model = Model.Lut(c) + model = Lut(c) else: - model = Model.Poly(c) + model = Poly(c) adapt.set_predistorter(model.get_dpd_data()) adapt.set_digital_gain(digital_gain) @@ -171,10 +169,10 @@ elif dpddata[0] == "lut": else: logging.error("Unknown dpd data format {}".format(dpddata[0])) -tx_agc = TX_Agc.TX_Agc(adapt, c) +tx_agc = TX_Agc(adapt, c) # Automatic Gain Control -agc = Agc.Agc(meas, adapt, c) +agc = Agc(meas, adapt, c) agc.run() state = "measure" @@ -191,7 +189,7 @@ while i < num_iter: # Extract usable data from measurement tx, rx, phase_diff, n_per_bin = extStat.extract(txframe_aligned, rxframe_aligned) - n_meas = Heur.get_n_meas(i) + n_meas = Heuristics.get_n_meas(i) if extStat.n_meas >= n_meas: # Use as many measurements nr of runs state = 'model' else: @@ -200,10 +198,10 @@ while i < num_iter: # Model elif state == 'model': # Calculate new model parameters and delete old measurements - lr = Heur.get_learning_rate(i) + lr = Heuristics.get_learning_rate(i) model.train(tx, rx, phase_diff, lr=lr) dpddata = model.get_dpd_data() - extStat = ExtractStatistic.ExtractStatistic(c) + extStat = ExtractStatistic(c) state = 'adapt' # Adapt diff --git a/dpd/src/Const.py b/dpd/src/Const.py index bf46796..ebdfeb2 100644 --- a/dpd/src/Const.py +++ b/dpd/src/Const.py @@ -6,9 +6,8 @@ import numpy as np class Const: - def __init__(self, sample_rate, target_median, n_bins, n_per_bin, n_meas): + def __init__(self, sample_rate, target_median, plot): self.sample_rate = sample_rate - self.n_meas = n_meas self.tx_gain_max = 89 @@ -41,11 +40,11 @@ class Const: self.phase_offset_per_sample = 1. / sample_rate * 2 * np.pi * 1000 # Constants for ExtractStatistic - self.ES_plot = False + self.ES_plot = plot self.ES_start = 0.0 self.ES_end = 1.0 - self.ES_n_bins = n_bins - self.ES_n_per_bin = n_per_bin + self.ES_n_bins = 64 + self.ES_n_per_bin = 128 # Constants for TX_Agc self.TAGC_max_txgain = 89 @@ -53,22 +52,21 @@ class Const: self.TAGC_tx_median_max = self.TAGC_tx_median_target*1.4 self.TAGC_tx_median_min = self.TAGC_tx_median_target/1.4 - self.RAGC_min_rxgain = 25 self.RAGC_rx_median_target = self.TAGC_tx_median_target # Constants for Model - self.MDL_plot = True + self.MDL_plot = True or plot # Override default # Constants for MER - self.MER_plot = False + self.MER_plot = plot # Constants for Model_PM self.MPM_tx_min = 0.1 # Constants for Measure_Shoulder self.MS_enable = False - self.MS_plot = False + self.MS_plot = plot assert sample_rate==8192000 meas_offset = 976 # Offset from center frequency to measure shoulder [kHz] meas_width = 100 # Size of frequency delta to measure shoulder [kHz] diff --git a/dpd/src/ExtractStatistic.py b/dpd/src/ExtractStatistic.py index bf9eba5..9df85bc 100644 --- a/dpd/src/ExtractStatistic.py +++ b/dpd/src/ExtractStatistic.py @@ -126,7 +126,8 @@ class ExtractStatistic: def _rx_value_per_bin(self): rx_values = [] for values in self.rx_values_lists: - rx_values.append(np.mean(np.abs(values))) + mean = np.mean(np.abs(values)) if len(values) > 0 else np.nan + rx_values.append(mean) return rx_values def _tx_value_per_bin(self): @@ -147,7 +148,8 @@ class ExtractStatistic: def _phase_diff_value_per_bin(self, phase_diffs_values_lists): phase_list = [] for values in phase_diffs_values_lists: - phase_list.append(np.mean(values)) + mean = np.mean(values) if len(values) > 0 else np.nan + phase_list.append(mean) return phase_list def extract(self, tx_dpd, rx): diff --git a/dpd/src/Heuristics.py b/dpd/src/Heuristics.py index 467c5da..a32ccff 100644 --- a/dpd/src/Heuristics.py +++ b/dpd/src/Heuristics.py @@ -10,7 +10,7 @@ import numpy as np def get_learning_rate(idx_run): idx_max = 10.0 lr_min = 0.05 - lr_max = 1 + lr_max = 0.4 lr_delta = lr_max - lr_min idx_run = min(idx_run, idx_max) learning_rate = lr_max - lr_delta * idx_run/idx_max @@ -24,5 +24,3 @@ def get_n_meas(idx_run): idx_run = min(idx_run, idx_max) learning_rate = n_meas_delta * idx_run/idx_max + n_meas_min return int(np.round(learning_rate)) - - diff --git a/dpd/src/TX_Agc.py b/dpd/src/TX_Agc.py index 7b74c8f..2602ea6 100644 --- a/dpd/src/TX_Agc.py +++ b/dpd/src/TX_Agc.py @@ -90,7 +90,7 @@ class TX_Agc: # Set new values. # Avoid temorary increase of output power with correct order - if digital_gain_factor < 0: + if digital_gain_factor < 1: self.adapt.set_digital_gain(digital_gain) time.sleep(0.5) txgain = self._set_tx_gain(new_txgain) diff --git a/dpd/src/Test_data.py b/dpd/src/Test_data.py index 67f4dff..bbef282 100644 --- a/dpd/src/Test_data.py +++ b/dpd/src/Test_data.py @@ -40,7 +40,7 @@ class Test_data: plt.plot(np.angle(np.fft.fftshift(np.fft.fft(tx_orig))), 'p') """ - self.c = src.Const.Const(sample_rate) + self.c = src.Const.Const(sample_rate,, False self.du = src.Dab_Util.Dab_Util(sample_rate) self.file_paths = { |