Scientific Computing

FMeXtra/VuCAST vs. HD Radio

FMeXtra can use 20% or 30% of the FM modulation, making up to 110% or 82.5 kHz deviation.

Main channel SCA modulation
mono 30 %
stereo 20 %

From Radio World reporting, the one-time cost of FMeXtra was ~ $10K, with no periodic licensing fees. The FMeXtra receivers were to be of comparable cost to HD Radio receivers; in fact the proposed FMeXtra receivers could also decode HD Radio, DRM, DAB, etc.

That seems like a great deal, and the Radio World testing showed that for 20% modulation depth, FMeXtra coverage was roughly comparable to -20 dBc HD Radio. So why did FMeXtra/VuCast fail to be adopted?

FMeXtra ROI

In effect we’re discussing energy/bit, which translates into energy/revenue for broadcasters. The most typical mode FMeXtra would be used in would be the mode preserving FM analog stereo and RDS, while precluding analog SCA. Thus, 62.5-98.5 kHz baseband in the lu;rds mode yielding 48 kbps, which could be split into 4 audio streams of low mono fidelity or 2 streams of medium fidelity or 1 stream of good fidelity (not quite high fidelity).

In comparison, HD Radio offers 96-120 kbps in hybrid and extended hybrid modes respectively. WCSP in Washington, D.C. with 4 digital subchannels has good audio quality. Music stations with 2 digital subchannels generally have good music audio quality, particularly as compared to the high artifacts of the old codecs used by Sirius XM SDARS satellite radio.

To make a digital transition worthwhile for the broadcaster and the listeners, there must be additional digital audio streams of at least FM stereo quality. That is, the sales staff must be able to sell advertisers on additional audio streams. Generally listeners are OK with analog FM on modern receivers that employ DSP stereo blending and diversity receive antennas, but prefer the clarity of 48-64 kbps AAC audio. HD Radio is an improvement in audio quality over analog FM, particularly in multipath prone urban environments, but what drives listeners to buy a new digital FM radio is extra subchannels.

RF bandwidth for FMeXtra vs. HD Radio: FMeXtra adds one additional music channel at 48 kbps. For talk subchannels, at least 16-24 kbps is preferred. HD Radio gives a high quality digital copy of the analog channel and adds a second high quality digital channel, or gives two additional digital-only music channels. HD Radio transmitter basic install is ~ $50K. So for about 4 times the capital cost for HD Radio over FMeXtra, the broadcaster gets 2.5 times the digital bitrate.

The appeal of RDS is the ability to build station affinity by showing callsign, current song playing, station phone #, etc. at least than $400 broadcaster hardware cost, while nearly every modern automotive receiver will display RDS as well as cell phones, the main means of FM listening. To invest $10K in FMeXtra, with no current receiver availability, is a non-starter, perpetuating the chicken and egg program of FMeXtra.

Back to the energy/bit argument, with HD Radio’s extended hybrid 120 kbps available for audio, the sales staff has 4 medium fidelity subchannels + 1 analog subchannel. Or, 1 analog + 2 high fidelity subchannels. What happens in urban areas is that a station will sell 1 or 2 medium fidelity subchannels to foreign language programming or talk radio that would normally be on an AM station + one medium-high fidelity copy of their analog channel. Or, one high fidelity copy of analog channel + one high fidelity second music channel.

FMeXtra in the same scenario adds two foreign language or talk radio or one music without helping the existing analog. FMeXtra has in effect one less music subchannel to sell vs. HD Radio–and that lost relative revenue keeps accumulating. Stations also get the benefit of more reliable modern equipment when upgrading, more amenable to remote operations and maintenance. The affluent customers reached first by HD Radio could demand higher CPM (advertising rates).

Successful ROI has been achieved by FM HD Radio stations able to:

  • lease HD subchannels to serve particular markets (instead of/in addition to AM broadcast)
  • HD-on-translator, where a large subset of main coverage is narrowcasted to college, minority, etc.
  • onboard advertisers of modest means on subchannel, revenue not reachable at main channel cost structure

These techniques implicitly on having lots of receivers in the field. With over a third of new automobiles having HD Radio–primarily affluent and high tech models, audiences appealing to advertisers, FMeXtra is nudged out by having no available receivers. 1/2 the digital subchannels for 1/4 one-time capital is offset in the ROI game.

When it comes to full digital HD Radio, FMeXtra is left in the dust as it’s currently a hybrid-only system. As with HDTV, broadcasters will be able to cut their transmitter power (and electricity bills) significantly, while offering better coverage, quality and more channels.

If FMeXtra were free to the broadcaster, they still may choose HD Radio for the ability to have twice as many subchannels and the entrenched market of receivers. DAB has tried and failed in North America (Canada) due to the dispersed population.


Related: FM SCA analysis with GNU Radio

View tree of USB devices on Windows/Linux

Microsoft USBView allows viewing connected USB devices on Windows in a tree view. This allows viewing which ports devices are plugged in to. USBView shows the name of chipsets and devices, even their serial numbers. An example use is computers in remote locations: verify that equipment is plugged in via USBView.

USBview

Linux USB View is available on GitHub. Follow the “INSTALL” file directions.

Send email via Gmail from Python

Note: This test should only be used with a new throwaway Gmail account as it risks security of the Gmail account in use. Instead consider Oauth with Gmail.


This is a complete example of SMTP sending email via Gmail from Python. To use with two-factor authentication account requires a Gmail App Password.

You need to use Oauth instead of this method for real-world systems, this is just a simple didactic example.

"""
send text string (e.g. status) via Gmail SMTP
"""
import smtplib
from email.mime.text import MIMEText
from getpass import getpass

def sender(user:str, passw:str, to:list, textmsg:str, server:str):
    """
    this is not a good way to do things.
    Should use Oauth.
    """
    with smtplib.SMTP_SSL('smtp.gmail.com') as s:
        s.login(user, passw)

        msg = MIMEText(textmsg)

        msg['Subject']= 'System status update'
        msg['From']= user
        msg['To'] = ', '.join(to)

        s.sendmail(user,to, msg.as_string())
        s.quit()

if __name__ == '__main__':
    from argparse import ArgumentParser
    p = ArgumentParser()
    p.add_argument('user',help='Gmail username')
    p.add_argument('to',help='email address(es) to send to', nargs='+')
    p.add_argument('-s','--server',help='SMTP server',default='smtp.gmail.com')
    p = p.parse_args()

    testmsg="just testing email from Python setup"

    sender(p.user+'@gmail.com',
           getpass('gmail password: '),
           p.to,
           testmsg,
           p.server)

Get Public IP address from Shell or Python

Both the shell and Python methods get public IPv4 and IPv6 addresses. This is good for verifying the computer IP is in the organization’s IP address range. These scripts use the “reflector” method, which can be more reliable on complex networks.

Shell: specify the network interface with curl --interface eth0 option.

Bash shell script “getIP.sh”

url=('https://ident.me' 'https://api.ipify.org')

for u in ${url[@]}; do
  curl -6 -s -m 2 $u && break
done

for u in ${url[@]}; do
  curl -4 -s -m 2 $u && break
done

Python script getIP.py

#!/usr/bin/env python
"""
gets interface IPv4 and IPv6 public addresses using libCURL
This uses the "reflector" method, which seems more reliable for finding public-facing IP addresses,
WITH THE CAVEAT that man-in-the-middle, etc. attacks can defeat the reflector method.
"""
from ipaddress import ip_address
import pycurl
from io import BytesIO

urls = ['https://ident.me', # ipv6 and ipv4
        'https://api.ipify.org'] # ipv4 only
length=45
# https://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address

def getip(interface=None):
    for url in urls:
        addr = []
        for ipv in (pycurl.IPRESOLVE_V4,pycurl.IPRESOLVE_V6):
            buffer = BytesIO() # must clear like this
            C = pycurl.Curl()
            if interface:
                C.setopt(pycurl.INTERFACE,interface)
            C.setopt(C.URL, url)
            C.setopt(pycurl.IPRESOLVE, ipv)
            C.setopt(C.WRITEDATA, buffer)
            try:
                C.perform()
                result = buffer.getvalue()
                try: #validate response
                    addr.append(ip_address(result.decode('utf8')))
                except ValueError:
                    pass
            except pycurl.error:
                pass
            finally:
                C.close()

        if len(addr)>1: #IPv4 and IPv6 found
            break

    return addr

if __name__ == '__main__':
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    from argparse import ArgumentParser
    p = ArgumentParser()
    p.add_argument('-i','--iface',help='network interface to use')
    p = p.parse_args()

    addr = getip(p.iface)
    print(addr)

Low priority Python execution

A data acquisition system typically runs multiple programs simultaneously:

  1. High-priority data collection - a program driving high data bandwidth acquisition
  2. Low-priority monitoring tools - check system status or process data
  3. Low-priority services - web servers displaying processed results

Properly prioritizing these processes ensures the critical data collection isn’t interrupted by secondary tasks.

Suppose a Python script “preview.py” is monitoring a camera’s status and needs to run at low priority.

On Unix-like systems (Linux, macOS, BSD, …) use nice to control process priority.

nice -n 19 python preview.py
nice -n
run task(s) with priority, where bigger positive numbers are lower priority, and more negative numbers are higher priority.

On Windows the start command can control program run priority.

start /low python preview.py
start /low
runs a program and its child processes at low priority.

Repairing broken symbolic link

A symbolic link may become broken due to updating/compiling/installing software, showing up as red text in ls Terminal.

Suppose the broken link is named “foo.so”: Find where link pointed to:

readlink -v foo.so

Point link to new file (perhaps foo2.so)

ln -sfn foo2.so foo.so

Verify new link is blue color

ls foo.so

Linux loopback audio record

Easily record the sounds heard through system speakers on Linux with Pulseaudio and Audacity.

apt install audacity pavucontrol

To record “what you hear” in Audacity: “click to monitor” (right of microphone in main Audacity screen). Start Pulseaudio advanced configuration tool

pavucontrol

Under pavucontrol Recording tab input, select “Monitor of Built-in XXX” where XXX is the playback device you wish to monitor. This loopback audio from pavucontrol allows recording what you hear in Linux using Audacity and PulseAudio.

PulseAudio loopback

List comments/annotations in PDF

On Windows, Adobe Reader can export and view a list of comments through the Comment tab on the right side. On Linux, in Evince PDF viewer, the side pane has a drop-down annotations menu that lists comments. Press F9 key if you don’t see the left-hand panel.

One can extract all comments and annotations from a PDF file by

apt install texlive-latex-extra

pdfannotextractor --install

pdfannotextractor in.pdf

This yields a .pax file without plain text. However, it was not clear how to read this file.

Open same PDF multiple times in Evince

It’s often useful to open the same PDF file multiple times, particularly when reviewing journal article drafts to view figures simultaneously with text describing the figure.

From Evince (popular Linux PDF viewer), Menu select “Open a Copy”. Open as many copies of the same Postscript or PDF document as desired.

Restarting Unity desktop in Ubuntu

This is for Ubuntu < 18.04. Ubuntu ≥ 18.04 no longer use Unity.


If the desktop seems to freeze for more than a few seconds, try

  1. press together the keys: Ctrl Alt F1
  2. login and type
unity & disown

This leaves desktop/apps all as they were while fixing the broken state.

Full desktop reset

Restart the whole Unity desktop (which is like unto logging out and logging in, discarding the current desktop):

service lightdm restart