Scientific Computing

Raspberry Pi WiFi Avahi mDNS config

Avahi mDNS allows connecting to the Raspberry Pi and other Avahi-enabled host devices without knowing the host IP address. The default /etc/avahi/avahi-daemon.conf puts mDNS on all active interfaces–including WiFi.

Manual config Avahi interfaces

This procedure is NOT typically needed. Find WLAN adapter name by

ip a

typically named wlan0. Also note the wlan0 IP address for testing if Avahi doesn’t work right away.

Edit /etc/avahi/avahi-daemon.conf to have

allow-interfaces=eth0,wlan0

or whatever interface desired to have Avahi on.

Verify which interfaces and IPv6/IPv6 Avahi is active on from the Avahi host device:

service avahi-daemon status

Test Raspberry Pi Avahi mDNS: from another computer:

ping hostname.local

If that doesn’t work, try using the IP address as found on Avahi host:

ip a

Configure firewall for SSH

Be sure to open the Raspberry Pi ufw firewall port. Port 22 (or other SSH port assigned in /etc/ssh/sshd_config on the Raspberry Pi) should be seen in:

ufw status

If you prefer a Firewall GUI:

apt install gufw

Avahi Diagnostics

Prereqs

apt install avahi-utils mdns-scan

From your laptop (or Pi if diagnosing)

avahi-browse -arp

or

mdns-scan

You should see your device (also try this from your Pi).

SSH security

Use SSH Public Key Authentication with ED25519 keys. Raspberry Pi is trivial to hack like any other device on any operating system if proper cybersecurity is not used. Why do you care if someone hacks your Pi? The hacker can use the Pi’s relatively powerful CPU & GPU to stage sophisticated attacks on the rest of your network.

Picking a simplex portable radio frequency

It’s generally much better to use 440 MHz band instead of 144 MHz band for portable hand-held radios (walkie-talkies). The 440 MHz signal is able to pierce through openings in buildings better. The interference from computers, LED lights, phone chargers, etc. is generally 20 dB or more less on 440 MHz vs. 144 MHz.

Generally we use “wide” 25 kHz bandwidth, as the performance is about 4 dB better than “narrow” 12.5 kHz spacing due to the nature of FM analog “processing” gain from wider bandwidth. That is, in the absence of interference, 25 kHz wide modulation performs significantly better than 12.5 kHz narrow modulation. Most members have analog-only radios at this time, so we kept with analog FM.

In North America, hams generally should not use FM below 442 MHz, as there are other modes coordinated for that frequency range. Hams should first consider 445.975, 446.0, or 446.025 MHz for FM simplex to be “safe” in most of North America, to not interfere with data links or repeater backbone links.

With modern radios after about year 2000 or so, there isn’t a significant advantage of one PL tone over another. There is too much bursty interference to run carrier squelch (no PL).

Python scripts from console / command prompt

Python packages can make Python scripts callable from any directory, by adding them to system PATH via the <PythonDistroRoot>/bin directory. On a typical Anaconda Python install, the shortcuts to these scripts are installed in a directory like ~/miniconda3/bin/

Make sure entry points are set up correctly before running pip install, or you will get the VersionConflict error (See Notes at bottom of this article).

Here is a simple example “src/mypkg/adder.py” to run directly from console (in any directory) as

add_two 6.75

to get result 8.75. Note that the end user doesn’t even know they’re running a Python script.

#!/usr/bin/env python3
from argparse import ArgumentParser


def add_two(x: float) -> float:
    return x + 2


def cli():
    p = ArgumentParser(description='adds two to number')
    p.add_argument('x', help='number to add two to', type=float)
    P = p.parse_args()

    print(add_two(P.x))

For each function you wish to have be accessible from anywhere on the system be sure there is a function that handles console arguments as in the example above.

Add to pyproject.toml:

[project.scripts]
add_two = mypkg.adder:cli

VersionConflict error may come from old entry_points in the Python distro bin/ directory that need to be removed.

f2py import Fortran code in Python

Importing Fortran code in Python just like any other Python module is very straightforward, using F2py. On any operating system, a Fortran compiler and Numpy are required to use F2py. If you don’t already have a Fortran compiler, we suggest GNU Gfortran.

  • macOS / Linux: using Homebrew: brew install gcc
  • Linux / Windows Subsystem for Linux: apt install gfortran
  • Windows: use MSYS2 pacman -S mingw-w64-ucrt-x86_64-gcc-fortran

Test/fix

Try the lowtran7 code. Following the instructions there, you should get

  1. A lowtran7.cp37-win_amd64.pyd (on Windows) or lowtran7*.so (on macOS / Linux) file
  2. Running python DemoLowtran.py creates a plot of atmospheric loss

Lowtran output

f2py does not allow inline comments for COMMON blocks

f2py does not allow inline comments for COMMON blocks for Fortran 77 .f code. This is because f2py works more strictly to Fortran specifications than most modern compilers.

Inline comments are not Fortran 77 standard, and will make f2py throw an error.

To fix this problem, just make the inline comment a full-line command with ! in column 1.

Fortran90 .f90 files won’t throw an f2py error due to inline comments on a line with a COMMON block: goodcomment.f90.

This will manifest itself two different ways, depending on whether you have implicit none or not:

COMMON inline comment error WITH implicit none

Example in badcomment_implicit.f:

var2fixfortran: No typespec for argument “x ! bad for fortran77”. getctype: No C-type found in “{}”, assuming void. KeyError: ‘void’

Solution: Make inline comment a full-line comment with ! in column 1.

COMMON inline comment error WITHOUT implicit none

Example in badcomment.f

error: expected ‘;’, ‘,’ or ‘)’ before ‘!’ token

Solution: Make inline comment a full-line comment with ! in column 1: goodcomment.f.

Windows troubleshooting

Another solution is to use Windows Subsystem for Linux with Anaconda Python. However, with the techniques below, I’ve always gotten f2py to work on Windows.

Tell Python to use MinGW by creating file ~/pydistutils.cfg containing:

[build]
compiler=mingw32

Do this from Powershell by copy/paste this line:

echo "[build]`ncompiler=mingw32" | Out-File -Encoding ASCII ~/pydistutils.cfg

‘f2py’ is not recognized as an internal or external command, operable program or batch file.

Ensure Numpy is installed

conda install numpy

(Windows) create a file <Anaconda Python install directory>/Scripts/f2py.bat with content

python %~dp0/f2py.py %*

Error: No module named ’numpy.distutils._msvccompiler’ in numpy.distutils; trying from distutils

is fixed by: create file ~/pydistutils.cfg as above


error LNK2001: unresolved external symbol _gfortran_st_write error LNK2001: unresolved external symbol _gfortran_st_read

and similar errors are typically from not having told f2py to use gfortran by: create file ~/pydistutils.cfg as above


An alternative to ~/pydistutils.cfg is for each F2py package install:

python setup.py build_ext --inplace --compiler=mingw32

If you have problems using f2py or other development work on Windows, consider Windows Subsystem for Linux, which runs at full performance within a terminal window on Windows.

Notes

Reference


Related: simple F2py Fortran examples

Update MiKTeX packages

Update MiKTeX packages to avoid issues with compiling documents. This is even true for a fresh MiKTeX install.

  1. Start → MiKTeX Console → Updates → Check for updates
  2. if updates available, click Update now

Anytime you get an unexpected error, try updating MiKTeX packages.

Convert IDL code to MATLAB

IDL2Matlab automatically partially converts IDL code to MATLAB / Octave code. However, this project appears to be abandoned; there haven’t been updates in a few years.

I avoid converting code if possible, because it can introduce subtle errors. Here are some alternatives to run the unmodified IDL code for free.

Try using free GDL that is compatible with IDL.

Another possibility is to call IDL from Python or Python from IDL.

Call GDL from Python by simply: import GDL see PYTHON.TXT

Install idl2matlab for Linux: download prereqs and code:

apt install libbison-dev flex

git clone https://github.com/farhi/idl2matlab

cd idl2matlab

Prepare to install in $HOME directory

./configure --prefix=$HOME

Edit Makefile

CFLAGS = -g -fno-stack-protector

Compile and install under $HOME

make && make install

The MATLAB code that idl2matlab produces uses a sort of cumbersome Matlab script that calls its own Matlab functions to do common tasks. The converted code can be further optimized. Still, probably easier than doing it all manually.

Completely undo errant git remote push

For any Git remote repo, you can undo (delete from git history) previous commits to eliminate wrong files via git push. If you only git revert, this leaves the big mess inside the .git directory, slowing down operations and wasting space.

Erase previous git commits

Before attempting recovery, copy local project to a remote backup location e.g. Dropbox.

Assuming it’s the last commit and push to delete from the Git history:

git reset --hard HEAD^
git push --force

Any time the git --force option is used, work can be permanently and irrecoverably lost, so always use care.

Reapply desired commit work

Copy any files from the old repo and make a new commit/push in the new repo. Every other computer with a copy of this repo will need to:

  1. make a backup copy of their local repo, if they did any work that needs to be saved
  2. git clone the repo again and likewise copy their changes back in.

Yes, they could git reset, but they might erase their work in that repo, if any.

Git remote write permissions

Implicit in this procedure is that those with write access to the remote Git repo can overwrite history, potentially causing permanent file loss. Remember that Git is a revision tracking system, NOT a backup system.

Restrict Git remote write access: for GitHub, from the repo branches Settings page, Add Rules according to the needs.