Bash scripts for Rohde&Schwarz ZVL network/spectrum analyzer

These are part of my efforts on remote controlling LXI enabled instruments using bash scripts. I started by writing the following wrapper for netcat - that way I can easily pipe stuff in and out. I named it "zvlcat" and placed it in /usr/local/bin/

#!/bin/bash
# Script for writing commands to and reading responses from
# a ZVL network analyzer. 
# Reading responses might fail if the response time is 
# greater than 1s.
#
# Usage: 
# zvlcat "some_command"  
# Sends "some_command" to ZVL. If cmd_str contains a "?",
# then it must be a query and the script waits for up to 
# 1 second for the reponse.
# The argument is optional and defaults to "*IDN?".

cmd_str="*IDN?"
opt_str=

# If argument was given, use it as command
if [ $# -gt 0 ]; then
    cmd_str=$1
fi

# Count number of question marks in command string
#  grep -o: put each find in new line
#  wc -l: count number of lines
num_quest=$(echo $cmd_str | grep -o "?" | wc -l)

# If there is a ? in the command, it's a query
# -> We should wait for 1 second for the reply.
if [ $num_quest -gt 0 ]; then
    opt_str="-q 1"
fi

echo $cmd_str | netcat $opt_str zvl.dhcp.mpi-hd.mpg.de 5025

I can then control the instrument using scripts such as this one:

#!/bin/bash

# This script performs a measurement of the ion amplitude
# using the ZVL network analyzer.

# Parameters
center="4.0565MHz"
rbw=1
aver_coun=50


# Reset instrument, activate spectrum analyser mode
zvlcat "*RST; INST:SEL SAN"

# single sweep mode, only sweep current channel
zvlcat "INIT:CONT OFF; SCOP SING"

# center frequency, span
zvlcat "FREQ:CENT $center; SPAN 100 Hz"

# filter type fft
zvlcat "BAND:TYPE FFT"

# bandwidth (seperate line because fft must be active at this point)
zvlcat "BAND $rbw"

# Set trace mode to average (Trace->Trace Mode->Average)
zvlcat "AVER ON; AVER:COUN $aver_coun"

# Set Range and Reference level
zvlcat "DISP:TRAC:Y 20; Y:RLEV -60"

# Calculate measurement time
swe_time=$(zvlcat "SWE:TIME?")
# This will be a float, but that's ok
meas_time=$(echo "($aver_coun * $swe_time)" | bc)

# Start single sweep, wait until it's finished
# (Note: This is the only "overlapping" command; needs *WAI)
zvlcat "INIT:IMM; *WAI"
sleep $meas_time

# Print to "Printer 1"
# zvlcat "HCOP 1"

# Read out the data (takes 1 second), write to file
# zvlcat "TRAC? TRACE1" > trace.dat

# I want to measure signal to noise. This is complicated, because
# I am not allowed to average over logarithms! Therefore I am using
# ZVL functions to do that

# Switch on marker
zvlcat "CALC:MARK:STAT ON"

# Put marker on peak
zvlcat "CALC:MARK:MAX"

# Read out marker
max_pow=$(./zvlcat "CALC:MARK:Y?")

# Activate noise measurement
zvlcat "CALC:MARK:FUNC:NOIS ON"

# Set marker lower by three divisions
zvlcat "CALC:MARK:X DOWN"
zvlcat "CALC:MARK:X DOWN"
zvlcat "CALC:MARK:X DOWN"

# Read out noise
nois_pow=$(zvlcat "CALC:MARK:FUNC:NOIS:RES?")

# Append values to file, including a timestamp
echo "RBW was $rbw"
echo "signal: $max_pow dBm"
echo "noise: $nois_pow dBm/Hz"
echo "$(date); $max_pow; $nois_pow" >> log_ion_vs_noise.txt

# Back this up.
# TO DO TO DO TO DO TO DO TO DO TO DO TO DO TO DO TO DO TO DO

# Turn on continous measurement again
zvlcat "INIT:CONT ON"

# Return to local control
zvlcat "@LOC"


###################
## DATA ANALYSIS ##
###################

# sed s/,/\\n/g trace.dat > rows.dat