Scientific Computing

Matlab buildtool subprojects

Matlab buildtool uses buildfile.m build plans that can each call other buildfile.m to stitch together Matlab subprojects from a top-level project. An example syntax for a top-level buildfile.m that invokes say Git submodule Matlab project is:

function plan = buildfile
plan = buildplan(localfunctions);
plan.DefaultTasks = "setup";
assert(~isMATLABReleaseOlderThan("R2024b"), "Subprojects with buildtool requires Matlab R2024b or newer")

end


function setupTask(context)

sub1 = fullfile(context.Plan.RootFolder, "MySubproject/buildfile.m")

% Matlab gitrepo() doesn't yet have the ability to run this command after cloning

if ~isfile(sub1)
  ok = system("git -C " + context.Plan.RootFolder + " submodule update --init --recursive");
  assert(ok == 0, "Failed to update MySubproject Git submodule");
end

buildtool("-buildFile", sub1, "setup")
% assumes that sub1 also has a task named setup that should be run

end

MacBook no boot with red battery icon

The red battery icon with a lightning bolt on a MacBook screen indicates that the battery is low and the Mac is not receiving enough power to boot. This can happen with a malfunctioning battery, an inadequate USB-C charger, or a damaged USB-C cable. If only the lightning bolt is under the red battery icon, this means the MacBook is receiving power via the USB-C port but there isn’t enough power to boot the MacBook. If there is a plug and lightning bolt under the red battery icon, this means the MacBook is not receiving power via the USB-C port.

This issue can arise when the MacBook battery has run out (0% charge) and the USB-C charger is not providing enough power to boot the MacBook. A solution is to find a USB-C (USB-PD) charger with at least 90 watts of power output to charge the MacBook battery to say 5% to 10% so that the MacBook can boot. One can then switch back to the lower wattage adapter that may take several hours to charge the MacBook battery. When traveling, especially with a high powered MacBook Pro, carry a USB-C adapter with at least the wattage of the original power adapter to avoid this issue. A temptation is to use say an iPhone or iPad lower wattage 15 W or 30 W charger with a MacBook Pro that may need 60 W or 90 W to boot from an empty battery.

Using the no boot checklist from Apple is also useful to troubleshoot the issue. It is uncommon to need to reset the SMC.

FFmpeg optimize YouTube video

FFmpeg can optimally re-encode video from numerous formats for YouTube (or other service) upload. YouTube suggested settings for SDR video are implemented below. There are additional settings for HDR Video.

ffmpeg -colorspace bt709 -i in.avi -b:v 8M -bufsize 16M -c:v libx264 -preset slow -c:a aac -b:a 384k -pix_fmt yuv420p -movflags +faststart out.mp4
-colorspace bt709
BT.709 color space for SDR video. HDR should not use this flag.
-i in.avi
input file
-b:v 8M -bufsize 16M
8 Mbps video bitrate with 16 Mbps buffer size. This assumes 1080p input video–adjust this to the actual resolution of the input video. Use the bitrate table to choose appropriately.
-c:v libx264
H.264 video codec
-preset slow
better encoding quality at expense of more processing time
-c:a aac
AAC-LC audio codec
-b:a 384k
384 kbps audio bitrate (stereo) – this is not the sample rate which should be 48 kHz
-pix_fmt yuv420p
YUV 4:2:0 pixel format
-movflags +faststart
moov atom at the beginning of the file
out.mp4
MP4 container as suggested by YouTube

Additional flags that can be set, but require knowing the video parameters like frame rate:

-flags +cgop -g 30
GOP of 30 frames – should be 1/2 frame rate so here it was a 60 fps video

Video only, without audio

ffmpeg -i in.avi -c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p -movflags +faststart out.mp4

Reference: FFmpeg for YouTube

GitHub Actions upload CMakeConfigureLog.yaml

When CMake fails on the configure or generate steps in a CI workflow, having CMakeConfigureLog.yaml uploaded a as a file can help debug the issue. Add this step to the GitHub Actions workflow YAML file:

  - name: Configure CMake
    run: cmake -B build

# other steps ...

  - name: upload CMakeConfigureLog.yaml
    if: failure() && hashFiles('build/CMakeFiles/CMakeConfigureLog.yaml') != ''
    uses: actions/upload-artifact@v4
    with:
      name: ${{ runner.os }}-${{ env.CC }}-CMakeConfigureLog.yaml
      path: build/CMakeFiles/CMakeConfigureLog.yaml
      retention-days: 5

The “retention-days” parameter is optional. Ensure the “name” parameter is unique to avoid conflicts with other jobs in the workflow. Here we assume that the OS and C compiler are unique between jobs.

Fortran stream buffering

Fortran programs, like most other programming languages, can access the standard input, output, and error streams, which usually connect to the terminal. Stream buffering generally increases efficiency of small bursts or groups of text typical to interactive applications. Buffering means that data is not immediately written to the terminal or console until the buffer is full or flushed. The Fortran statement to flush is flush(unit), where unit is the unit number of the stream to flush. Fortran statement print automatically flush the stream. Fortran statement write flushes the stream unless the advance specifier is set to no.

Different compilers have distinct default stream buffering behavior.

  • Gfortran: streams buffered by default. Environment variable GFORTRAN_UNBUFFERED_PRECONNECTED can be set to “y” to disable buffering.
  • Intel Fortran “ifx”: streams unbuffered by default. Environment variable FORT_BUFFERED can be set to “TRUE” to enable buffering.

Matlab reading CDF files

NASA CDF data file format can be read in many languages including Matlab. Matlab data file interfaces don’t always yield an obvious error message if something is wrong like a data file doesn’t exist or a variable doesn’t exist in a data file. For CDF, the message for cdfread of a non-existent variable is like:

Error using matlab.internal.imagesci.cdflib

CDF library failure encountered when executing the CDFclosezVar routine: “ILLEGAL_IN_zMODE: Operation is illegal while in zMode.”

One can use try-catch or check that the variable name exists with cdfinfo .Variables column 1.

Install latest LLVM Clang / Flang on GitHub Actions

The Clang / Flang compiler versions on GitHub Actions might be older than desired. While GCC is usually the latest release on GA, LLVM might be a couple versions behind latest. This example shows how to install a range of LLVM versions in a GitHub Actions workflow.


jobs:

  linux-flang:
    runs-on: ubuntu-latest
    timeout-minutes: 15

    strategy:
      matrix:
        llvm-version: [20]

    env:
      CC: clang-${{ matrix.llvm-version }}
      CXX: clang++-${{ matrix.llvm-version }}
      FC: flang-${{ matrix.llvm-version }}

    steps:
    - uses: actions/checkout

    - name: Apt LLVM
      run: |
          wget https://apt.llvm.org/llvm.sh
          chmod +x llvm.sh
          sudo ./llvm.sh ${{ matrix.llvm-version }}
          sudo apt-get update

    - name: install Flang
      run: sudo apt install --no-install-recommends clang-${{ matrix.llvm-version }} flang-${{ matrix.llvm-version }}

    # build , test, etc.

Matlab builtin() function overload

Matlab built-in functions can be overloaded in classes or in general. This can be useful when making code compatible with both Matlab and GNU Octave, or to be compatible with older Matlab versions.

For example, the Matlab built-in function strlength gets the length of char and string arrays, but older Matlab and GNU Octave don’t have this function. We made a function in strlength.m in a project’s private/ directory like:

%% STRLENGTH get length of character vector or scalar string

function L = strlength(s)

L = [];

if ischar(s)
  L = length(s);
elseif isstring(s)
  L = builtin('strlength', char(s));
  % char() is workaround for bug described below
end

end

A bug we found and confirmed by Xinyue Xia of Mathworks Technical Support is as follows: strlength() works with char, or string scalars or N-D arrays. However, when using

builtin('strlength')

only char is accepted. Scalar or N-D string array errors unexpectedly.

Example:

builtin('strlength', ["hi", "there"])

we expect to get [2,5] but instead get:

Error using strlength First argument must be text.

builtin('strlength', "hi")

expect value 2, but instead get

Error using strlength First argument must be text.

Matlab remote desktop plot rendering

Matlab graphics rendering can break with remote desktop via VNC or X11 forwarding. Local Matlab plots can break due to GPU graphics driver problems. Before Matlab R2025a, setting Matlab figure renderer could workaround Matlab plot issues. Consider using Matlab Online for remote development if available.

f = figure;

% Obsolete as of Matlab R2025a
set(f, Renderer='painters', RendererMode='manual')

Matlab rendererinfo() provides extensive details about the rendering backend.

Conda commands fail with Windows PowerShell 7.5

With Conda older than 25.0 on Windows, upon upgrading to PowerShell 7.5, all Conda commands might fail like:

Invoke-Expression: Cannot bind argument to parameter ‘Command’ because it is an empty string.

The underlying issue is the faulty syntax of the Conda scripts.

The easiest solution is to uninstall and reinstall Miniconda or Anaconda.