Scientific Computing

Get list of CMake target names

CMake build targets are declared by “add_[executable,library,custom_target]” commands. Targets can be dynamically set by arbitrarily complex foreach(), if(), etc. logic. A list of CMake targets in the directory scope is retrieved by the BUILDSYSTEM_TARGETS directory property.

The variable “target_names” contains all the target names previously added in the CMakeLists.txt in the DIRECTORY scope. Retrieving the list of targets in a whole project, or in a FetchContent dependency is possible with this CMake function:

function(print_targets dir)
    get_property(subdirs DIRECTORY "${dir}" PROPERTY SUBDIRECTORIES)
    foreach(sub IN LISTS subdirs)
        print_targets("${sub}")
    endforeach()

    get_directory_property(targets DIRECTORY "${dir}" BUILDSYSTEM_TARGETS)
    if(targets)
        message("Targets in ${dir}:")
        foreach(t IN LISTS targets)
            message("  • ${t}")
        endforeach()
    endif()
endfunction()

Use this function like:

print_targets("${CMAKE_CURRENT_SOURCE_DIR}")

Or supposing FetchContent, here using “googletest”:

FetchContent_MakeAvailable(googletest)

FetchContent_GetProperties(googletest)
print_targets(${googletest_SOURCE_DIR})

results in:

Targets in _deps/googletest-src/googletest:
  • gtest
  • gtest_main
Targets in _deps/googletest-src/googlemock:
  • gmock
  • gmock_main

Note: get_property(test_names GLOBAL PROPERTY BUILDSYSTEM_TARGETS) will return an empty list–DIRECTORY scope must be used.

4G / 5G WWAN Ethernet routers

Reliable cellular router specifications include:

  • External antenna (system + router is inside rugged weatherproof metal enclosure)

  • Wired (Ethernet) connection to equipment versus WiFi only for robustness

  • WiFi if desired vs. wired network only

  • USB only network connection. Some cheap routers have only USB (no Ethernet) connection to a consumer modem. Don’t allow one computer going down to take down connectivity to the whole site.

  • Setup via web or SSH

  • consider if higher-end models with 5G or CBRS mobile network support are needed.

  • Transfer Rate: 50 Mbps Up, 100 Mbps Down

  • WWAN antenna: 2 or more with connectors for coax cable

  • Ethernet: 100 / 1000 Mbps

  • Antenna: perhaps a broadband log periodic to give continuous frequency coverage to the numerous LTE bands.

ConnectBot import OpenSSH keys

The open source SSH app ConnectBot allows connecting to SSH servers with port forwarding using public key authentication, including ED25519. Generally users should create unique SSH public/private keypairs for each device. Sharing keys between devices means if a device is compromised, deleting its key from ~/.ssh/authorized_keys on the SSH server disables all other devices sharing that key.

If necessary, ConnectBot can import OpenSSH keys created on a PC.

Cinepak video for Fiji / ImageJ

Fiji / ImageJ cannot directly read Cinepak codec video files. Convert from Cinepak to popular video formats using FFmpeg. This conversion can be done on the command line as in this article, via an FFmpeg import plugin. Motion JPEG is widely-compatible with video players including ImageJ.

ffmpeg -i old.avi -c:v mjpeg -q:v 1 out.avi

Uncompressed AVI output file size could be a factor of 10 larger than the Cinepak version. By definition, every video player should be able to play uncompressed AVI–including ImageJ.

ffmpeg -i old.avi -c:v rawvideo out.avi

Lossless FFV1 preserves the original video quality with lossless compression. Many video players can handle FFV1 AVI video.

ffmpeg -i old.avi -c:v ffv1 out.avi

The advantage of using a PNG image stack comes in frame-by-frame analysis of the video.

Consider converting video to HDF5 using dmcutils/avi2hdf5.py for analysis purposes.

Compact WSL Disk Image unused space

Windows Subsystem for Linux (WSL) uses VHDX files to store each distribution’s filesystem. Over time these disk images grow in size as files are added and deleted. However, the space used by deleted files is not automatically reclaimed, leading to larger disk images than necessary.

There is a PowerShell script to automatically compact WSL VHDX files that works with any of the Windows release levels (including Home).

JPEG lossless rotate, crop, flip with jpegtran

The jpegtran command line tool allows lossless transformations on JPEG images, including rotation, cropping, and flipping. This is particularly useful when you want to modify JPEG images without re-encoding them, which can lead to quality loss.

Example: lossless clockwise 90 degree rotation of a JPEG image “input.jpg” and save the result to file “output.jpg”:

jpegtran -rotate 90 input.jpg > output.jpg

Check outbound network ports with Python

WiFi captive portals and public networks often block outbound network port traffic. Sometimes even VPNs are blocked. Often only ports 80 (HTTP) and 443 (HTTPS) are allowed.

For Git, one can use Git with HTTPS and Oauth tokens instead of Git over SSH, or use Git with SSH over port 443. Git over SSH has certain benefits for ease of use and security.

To quickly determine if outbound network ports are blocked, portquiz.net is a useful free service. Using Python automates this process for multiple ports concurrently using concurrent.futures.ThreadPoolExecutor threads or asyncio. We provide an example of each method in short scripts. The examples shows that Asyncio using Semaphore with AIOHTTP can be faster than ThreadPoolExecutor with urllib.request.

Solutions to blocked ports for SSH include using SSH ProxyJump with an intermediate TRUSTED server on an allowed port. Some remote SSH systems actually require this, where they the desired server has only LAN access, and a gateway SSH server with no privileges is used as the SSH ProxyJump by network design.

The ultimate workaround would be a mobile hotspot (different network).

LaTeX syntax highlight with Minted

LaTeX code highlighting is possible using the minted LaTeX package, which uses Pygments as a backend. Minted is available in Overleaf as well.

If needed, install minted via TeX Live Manager (tlmgr)

tlmgr install minted

Install Python Pygments:

python -m pip install pygments
# or
brew install pygments

If using a GUI, the --shell-escape option may need to be added. In TeXmaker / TeXstudio, under “Options → Configure → Commands” add --shell-escape right after the compiler executable like xelatex --shell-escape or pdflatex --shell-escape or latexmk --shell-escape.

If “pygmentize” isn’t found, under TeXstudio Preferences → Build, check Show Advanced Options in the lower left checkbox and set Additional Search Paths → Commmands ($PATH) to the directory containing “pygmentize”, e.g. /opt/homebrew/bin on macOS with Homebrew or whatever directory comes up for which pygmentize in a Terminal.

Python asyncio OSError 24 too many open files

In general operation systems set a limit to the number of open files per process. A “file” might be a regular file, a socket, a pipe, etc. When a Python program exceeds this limit, it raises exception:

OSError: [Errno 24] Too many open files

Such issues might tend to arise with highly concurrent applications as enabled by asyncio or higher-level libraries. Resolving such asyncio concurrency issues generally involves asyncio primitives like asyncio.Semaphore. Implementing asyncio libraries correctly is so non-trivial that using higher-level libraries that implement such concurrency control correctly can be a better idea. It’s important to go beyond toy examples and consider real-world concurrent Python usage patterns.

CMake Position Independent Code

Certain projects with legacy build systems like Make or Autotools or in general may specify to build with flags like “-fPIC” for position independent code (PIC) on Linux systems. Consider not forcing these flags in CMake projects if there isn’t a specific known need, to let users and consuming projects decide whether they need PIC or not. When PIC is needed, do like:

if(...)
  include(CheckPIESupported)

  check_pie_supported()

  set(CMAKE_POSITION_INDEPENDENT_CODE true)
endif()

The check_pie_supported module checks whether the compiler supports PIE and should be run before setting target property POSITION_INDEPENDENT_CODE.

When PIC is enabled with certain platforms like Intel oneAPI on Linux, linker errors may result like

relocation R_X86_64_32 against `.rodata.str1.1’ can not be used when making a PIE object

where the solution is to disable PIC – or simply do not enable it by default in the CMake project as we suggested above.