← All notes
pTx, scanner hacks

How to recover a static B1 shim solution from a DICOM file

Every DICOM stores the pTx shim weights the scan was run with. One command reads them out and turns them into an AdjValidate command you can run on the scanner.

You need this when:

  • you deleted the B1 shim cache by accident,
  • you are checking a scan after the fact, or
  • you want the exact same shim solution for the same head in a later session.

1. Run one command on the DICOM

On Linux or a Mac, replace scan.dcm with your file name and paste this into a terminal:

grep -a 'aTxScaleFactor\[' scan.dcm | awk '
  { split($1, p, /[][]/); ch = p[2] + 0; if (ch >= n) n = ch + 1 }
  $1 ~ /dRe$/ { re[ch] = $NF }
  $1 ~ /dIm$/ { im[ch] = $NF }
  END {
    printf "AdjValidate -txscale -set"
    for (i = 0; i < n; i++)
      printf " %.4f %.4f", sqrt(re[i]^2 + im[i]^2), atan2(im[i], re[i]) * 45 / atan2(1, 1)
    print ""
  }' > Excitation_B1_solution.txt

On Windows, open PowerShell in the folder with the DICOM, change scan.dcm in the first line and paste the whole block:

$file = "scan.dcm"
$inv = [Globalization.CultureInfo]::InvariantCulture
$text = [IO.File]::ReadAllText((Resolve-Path $file))
$re = @{}; $im = @{}; $n = 0
foreach ($m in [regex]::Matches($text, 'aTxScaleFactor\[(\d+)\]\.d(Re|Im)\s*=\s*(\S+)')) {
  $ch = [int]$m.Groups[1].Value
  $v = [double]::Parse($m.Groups[3].Value, $inv)
  if ($m.Groups[2].Value -eq "Re") { $re[$ch] = $v } else { $im[$ch] = $v }
  if ($ch -ge $n) { $n = $ch + 1 }
}
$out = "AdjValidate -txscale -set"
for ($i = 0; $i -lt $n; $i++) {
  $r = [double]$re[$i]; $j = [double]$im[$i]
  $out += " " + [math]::Sqrt($r*$r + $j*$j).ToString("F4", $inv) + " " + ([math]::Atan2($j, $r) * 180 / [math]::PI).ToString("F4", $inv)
}
Set-Content Excitation_B1_solution.txt $out

Excitation_B1_solution.txt now holds one AdjValidate command with a magnitude and phase (in degrees) pair per transmit channel.

2. Load the solution on the scanner

Either load the file in the B1 shim cache tool, or paste the line into the command shell at the scanner while a sequence is open for editing.

Excitation_B1_solution.txt containing a single AdjValidate -txscale -set command with a magnitude and phase pair per channel.

What the command does

Siemens writes the full protocol into every DICOM as plain text, and the shim weights are in it as sTXSPEC.aTxScaleFactor. Raw .dat files contain the same block, so the command works on them too. You can see the values yourself by opening the DICOM as plain text in an editor such as VS Code and searching for aTxScaleFactor:

VS Code search for aTxScaleFactor in a DICOM file, showing the real and imaginary scale factor for each transmit channel.

Each channel has a real (.dRe) and an imaginary (.dIm) value. AdjValidate expects magnitude and phase, so the command converts each pair.

  • grep -a pulls the matching lines out of the binary file. awk alone can fail on binary data.
  • Siemens leaves out values that are exactly zero, so a channel can have a .dRe line but no .dIm line. The script matches values by channel number and treats a missing value as 0, so the channels stay in the right order.

Written by Nils Nothnagel, MRI pulse sequence developer at CMRR, University of Minnesota. nilsnothnagel.com