95 lines
2.8 KiB
Bash
95 lines
2.8 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
#
|
||
|
|
# Run a noise-floor capture and analyse it in one step.
|
||
|
|
#
|
||
|
|
# Wraps logger.py -- every logger flag is accepted and passed straight through --
|
||
|
|
# then runs plot.py and characterize.py on whatever was captured. Works whether
|
||
|
|
# the run ends on --duration or on Ctrl-C.
|
||
|
|
#
|
||
|
|
# ./noise_floor_test.sh --duration 60
|
||
|
|
# ./noise_floor_test.sh --duration 3600 --cycle-count 400
|
||
|
|
# ./noise_floor_test.sh # until Ctrl-C
|
||
|
|
#
|
||
|
|
# Anything you pass explicitly wins; otherwise logger.py's defaults apply.
|
||
|
|
|
||
|
|
set -uo pipefail # deliberately not -e: logger.py exits 1 on a miss,
|
||
|
|
# and a partial capture is still worth analysing.
|
||
|
|
|
||
|
|
cd "$(dirname "$0")"
|
||
|
|
|
||
|
|
if [[ ! -f .venv/bin/activate ]]; then
|
||
|
|
echo "No virtualenv found. Run ./setup.sh first." >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
# shellcheck disable=SC1091
|
||
|
|
source .venv/bin/activate
|
||
|
|
|
||
|
|
args=("$@")
|
||
|
|
|
||
|
|
has_flag() {
|
||
|
|
local needle=$1 a
|
||
|
|
for a in "${args[@]:-}"; do
|
||
|
|
[[ "$a" == "$needle" || "$a" == "$needle="* ]] && return 0
|
||
|
|
done
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
|
||
|
|
# The CSV path has to be known up front so the analysis can find it; logger.py
|
||
|
|
# would otherwise pick a timestamped name we cannot predict without racing it.
|
||
|
|
output=""
|
||
|
|
for ((i = 0; i < ${#args[@]}; i++)); do
|
||
|
|
case "${args[i]}" in
|
||
|
|
--output=*) output="${args[i]#--output=}" ;;
|
||
|
|
--output|-o) output="${args[i+1]:-}" ;;
|
||
|
|
esac
|
||
|
|
done
|
||
|
|
if [[ -z "$output" ]]; then
|
||
|
|
output="noise_$(date +%Y%m%d_%H%M%S).csv"
|
||
|
|
args+=(--output "$output")
|
||
|
|
fi
|
||
|
|
|
||
|
|
has_flag --bus-speed || args+=(--bus-speed 750)
|
||
|
|
|
||
|
|
echo "=== capture -> $output ==="
|
||
|
|
# Ctrl-C reaches the whole foreground process group. Trapping it here stops bash
|
||
|
|
# killing the script, so logger.py can shut down cleanly and the analysis below
|
||
|
|
# still runs. A no-op trap (not 'ignore') keeps the child's own handling intact.
|
||
|
|
trap ':' INT
|
||
|
|
python logger.py "${args[@]}"
|
||
|
|
capture_rc=$?
|
||
|
|
trap - INT
|
||
|
|
|
||
|
|
# A non-zero logger exit covers both "aborted mid-capture" and "never started"
|
||
|
|
# (no adapter, bad flag). Whether a usable file exists is what distinguishes
|
||
|
|
# them, so check that before claiming anything about the data.
|
||
|
|
if [[ ! -s "$output" ]]; then
|
||
|
|
echo
|
||
|
|
echo "Capture produced no data (exit $capture_rc); nothing to analyse." >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
if [[ "$capture_rc" -ne 0 ]]; then
|
||
|
|
echo
|
||
|
|
echo "Capture ended early (exit $capture_rc). Analysing what was recorded --" \
|
||
|
|
"it is valid up to that point." >&2
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "=== plot ==="
|
||
|
|
python plot.py "$output"
|
||
|
|
plot_rc=$?
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "=== characterize ==="
|
||
|
|
python characterize.py "$output"
|
||
|
|
char_rc=$?
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "=== outputs ==="
|
||
|
|
base="${output%.csv}"
|
||
|
|
for f in "$output" "$base.png" "${base}_noise.png"; do
|
||
|
|
[[ -f "$f" ]] && printf ' %-40s %8s\n' "$f" "$(du -h "$f" | cut -f1)"
|
||
|
|
done
|
||
|
|
|
||
|
|
# Non-zero if any stage failed, so this is usable from a scheduler.
|
||
|
|
[[ $capture_rc -eq 0 && $plot_rc -eq 0 && $char_rc -eq 0 ]] || exit 1
|