Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
/packages/ham/bench
bunnyhutch_id_rsa
/_tmp/
/_temp/
/_output/
/_benchmark_output/
/tmp.csv
/tmp-cluster-annotations.csv
/packages/ig-sw/src/ig_align/ig-sw
Expand Down Expand Up @@ -63,3 +65,4 @@ packages/RPANDA/lib/
/build/
/dist/
/partis_bcr.egg-info/
_ignore/
2 changes: 1 addition & 1 deletion bin/partis
Original file line number Diff line number Diff line change
Expand Up @@ -1641,7 +1641,7 @@ parent_args.append({'name' : '--get-selection-metrics', 'kwargs' : {'action' : '
parent_args.append({'name' : '--min-selection-metric-cluster-size', 'kwargs' : {'type' : int, 'default' : treeutils.default_min_selection_metric_cluster_size, 'help' : 'When calculating selection metrics, ignore clusters smaller than this. See also --min-paired-cluster-size-to-read, which is similar but applies earlier, when reading clusters from files.'}})
parent_args.append({'name' : '--min-paired-cluster-size-to-read', 'kwargs' : {'type' : int, 'default' : treeutils.default_min_selection_metric_cluster_size, 'help' : 'When reading paired annotations when getting selection metrics or plotting partitions, ignore clusters with either N h or l ids smaller than this. See also --min-selection-metric-cluster-size, which is similar but only skips selection metric calculation.'}})
parent_args.append({'name' : '--treefname', 'kwargs' : {'help' : 'newick-formatted file with a tree corresponding to the sequences either in --infname (if making new output, i.e. action is annotate or partition) or --outfname (if reading existing output, i.e. action is get-selection-metrics). Used for instance if getting selection metrics using trees inferred by an external program (unrelated to --input-simulation-treefname).'}})
parent_args.append({'name' : '--tree-inference-method', 'kwargs' : {'choices' : ['fasttree', 'iqtree', 'iqtree-1.6.beta3', 'iqtree-2.3.1', 'raxml', 'gctree', 'gctree-base', 'gctree-mut-mult', 'gctree-no-dag', 'linearham', 'igphyml', 'cpath'], 'help' : 'Method to use when inferring trees (default: fasttree)'}})
parent_args.append({'name' : '--tree-inference-method', 'kwargs' : {'choices' : ['fasttree', 'iqtree', 'iqtree-1.6.beta3', 'iqtree-2.3.1', 'raxml', 'gctree', 'gctree-base', 'gctree-mut-mult', 'gctree-no-dag', 'linearham', 'igphyml', 'bcrlarch-pars', 'cpath'], 'help' : 'Method to use when inferring trees (default: fasttree)'}})
parent_args.append({'name' : '--tree-inference-subdir', 'kwargs' : {'help' : 'Subdirectory of the (automatically-set) tree inference workdir to which to write tree inference output files. By default, these are written to a subdir of --outfname/--paired-outdir with the name of the inference method, but this argument allows multiple versions, as with --sub-plotdir.'}})
parent_args.append({'name' : '--infer-trees-with-only-leaves', 'kwargs' : {'action' : 'store_true', 'help' : 'Discard internal nodes in true trees when inferring phylogenetic trees.'}})
parent_args.append({'name' : '--infer-trees-with-collapsed-duplicate-seqs', 'kwargs' : {'action' : 'store_true', 'help' : 'collapse identical sequences when inferring trees (and then again when plotting them, since unfortunately it\'s really hard to pass the information between those two scripts). Yes, it sucks having both this and --collapse-duplicate-sequences (which acts during smith-waterman), but sometimes we can\'t use that, e.g. with queries to include or subset partitioning (at least without more work).'}})
Expand Down
285 changes: 123 additions & 162 deletions bin/xvfb-run
Original file line number Diff line number Diff line change
@@ -1,194 +1,155 @@
#!/bin/sh
# ----------------------------------------------------------------------------------------
# NOTE copied from ubuntu system location in order to remove the '2>&1' at the bottom, see https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/1059947
# ----------------------------------------------------------------------------------------

# This script starts an instance of Xvfb, the "fake" X server, runs a command
# with that server available, and kills the X server when done. The return
# value of the command becomes the return value of this script, except in cases
# where this script encounters an error.
#
# If anyone is using this to build a Debian package, make sure the package
# Build-Depends on xvfb and xauth.

set -e

PROGNAME=xvfb-run
SERVERNUM=99
AUTHFILE=
ERRORFILE=/dev/null
XVFBARGS="-screen 0 640x480x8"
LISTENTCP="-nolisten tcp"
XAUTHPROTO=.

# Query the terminal to establish a default number of columns to use for
# displaying messages to the user. This is used only as a fallback in the event
# the COLUMNS variable is not set. ($COLUMNS can react to SIGWINCH while the
# script is running, and this cannot, only being calculated once.)
DEFCOLUMNS=$(stty size 2>/dev/null | awk '{print $2}') || true
if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" >/dev/null 2>&1; then
DEFCOLUMNS=80
fi
# Robust xvfb-run wrapper for headless / HPC environments
#
# Key features:
# - Clear error logging
# - No use of `tempfile`, `$$`, or explicit XXXXX templates
# - Falls back to running command directly if Xvfb is unavailable
# - Forces headless plotting backends when falling back
#

# Display a message, wrapping lines at the terminal width.
message () {
echo "$PROGNAME: $*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS}
}
set -u

# Display an error message.
error () {
message "error: $*" >&2
}
PROGNAME="$(basename "$0")"

SERVERNUM=""
AUTO_SERVERNUM=""
ERRORFILE=""
XVFBARGS="-screen 0 1280x1024x24"
XVFB_RUN_TMPDIR=""
AUTHFILE=""
XVFBPID=""

XAUTHORITY_ORIG="${XAUTHORITY-}"
DISPLAY_ORIG="${DISPLAY-}"

usage() {
cat >&2 <<EOF
Usage: ${PROGNAME} [OPTIONS] command [args...]

# Display a usage message.
usage () {
if [ -n "$*" ]; then
message "usage error: $*"
fi
cat <<EOF
Usage: $PROGNAME [OPTION ...] COMMAND
Run COMMAND (usually an X client) in a virtual X server environment.
Options:
-a --auto-servernum try to get a free server number, starting at
--server-num
-e FILE --error-file=FILE file used to store xauth errors and Xvfb
output (default: $ERRORFILE)
-f FILE --auth-file=FILE file used to store auth cookie
(default: ./.Xauthority)
-h --help display this usage message and exit
-n NUM --server-num=NUM server number to use (default: $SERVERNUM)
-l --listen-tcp enable TCP port listening in the X server
-p PROTO --xauth-protocol=PROTO X authority protocol name to use
(default: xauth command's default)
-s ARGS --server-args=ARGS arguments (other than server number and
"-nolisten tcp") to pass to the Xvfb server
(default: "$XVFBARGS")
-a Automatically choose a free X server number (starting at 99)
-n NUM Use X server number NUM
-e FILE Append logs to FILE (default: stderr only)
-s ARGS Extra arguments for Xvfb
-h Show this help

Behavior:
If Xvfb is not available on PATH, the command is run directly with
headless backends forced (MPLBACKEND=Agg, QT_QPA_PLATFORM=offscreen).
EOF
}

# Find a free server number by looking at .X*-lock files in /tmp.
find_free_servernum() {
# Sadly, the "local" keyword is not POSIX. Leave the next line commented in
# the hope Debian Policy eventually changes to allow it in /bin/sh scripts
# anyway.
#local i

i=$SERVERNUM
while [ -f /tmp/.X$i-lock ]; do
i=$(($i + 1))
done
echo $i
log() {
msg="[$PROGNAME] $*"
echo "$msg" >&2
if [ -n "$ERRORFILE" ]; then
echo "$msg" >>"$ERRORFILE" 2>/dev/null || true
fi
}

# Clean up files
clean_up() {
if [ -e "$AUTHFILE" ]; then
XAUTHORITY=$AUTHFILE xauth remove ":$SERVERNUM" >>"$ERRORFILE" 2>&1
die() {
log "ERROR: $*"
exit 1
}

cleanup() {
if [ -n "$XVFBPID" ] && kill -0 "$XVFBPID" 2>/dev/null; then
kill "$XVFBPID" 2>/dev/null || true
wait "$XVFBPID" 2>/dev/null || true
fi
if [ -n "$XVFB_RUN_TMPDIR" ] && [ -d "$XVFB_RUN_TMPDIR" ]; then
rm -rf "$XVFB_RUN_TMPDIR" 2>/dev/null || true
fi
if [ -n "$XVFB_RUN_TMPDIR" ]; then
if ! rm -r "$XVFB_RUN_TMPDIR"; then
error "problem while cleaning up temporary directory"
exit 5
fi
if [ -n "$XAUTHORITY_ORIG" ]; then
export XAUTHORITY="$XAUTHORITY_ORIG"
else
unset XAUTHORITY 2>/dev/null || true
fi
if [ -n "$XVFBPID" ]; then
kill "$XVFBPID" >>"$ERRORFILE" 2>&1
if [ -n "$DISPLAY_ORIG" ]; then
export DISPLAY="$DISPLAY_ORIG"
else
unset DISPLAY 2>/dev/null || true
fi
}

# Parse the command line.
ARGS=$(getopt --options +ae:f:hn:lp:s:w: \
--long auto-servernum,error-file:,auth-file:,help,server-num:,listen-tcp,xauth-protocol:,server-args:,wait: \
--name "$PROGNAME" -- "$@")
GETOPT_STATUS=$?

if [ $GETOPT_STATUS -ne 0 ]; then
error "internal error; getopt exited with status $GETOPT_STATUS"
exit 6
fi

eval set -- "$ARGS"

while :; do
case "$1" in
-a|--auto-servernum) SERVERNUM=$(find_free_servernum); AUTONUM="yes" ;;
-e|--error-file) ERRORFILE="$2"; shift ;;
-f|--auth-file) AUTHFILE="$2"; shift ;;
-h|--help) SHOWHELP="yes" ;;
-n|--server-num) SERVERNUM="$2"; shift ;;
-l|--listen-tcp) LISTENTCP="" ;;
-p|--xauth-protocol) XAUTHPROTO="$2"; shift ;;
-s|--server-args) XVFBARGS="$2"; shift ;;
-w|--wait) shift ;;
--) shift; break ;;
*) error "internal error; getopt permitted \"$1\" unexpectedly"
exit 6
;;
trap cleanup EXIT HUP INT TERM

# Parse options
while getopts "an:e:s:h" opt; do
case "$opt" in
a) AUTO_SERVERNUM=1 ;;
n) SERVERNUM="$OPTARG" ;;
e) ERRORFILE="$OPTARG" ;;
s) XVFBARGS="$XVFBARGS $OPTARG" ;;
h) usage; exit 0 ;;
*) usage; exit 2 ;;
esac
shift
done
shift $((OPTIND - 1))

if [ "$SHOWHELP" ]; then
usage
exit 0
fi
[ "$#" -ge 1 ] || { usage; exit 2; }

if [ -z "$*" ]; then
usage "need a command to run" >&2
exit 2
# --- Fallback path: no Xvfb available ---
if ! command -v Xvfb >/dev/null 2>&1; then
log "WARNING: Xvfb not found; running command without virtual display."
export MPLBACKEND="${MPLBACKEND-Agg}"
export QT_QPA_PLATFORM="${QT_QPA_PLATFORM-offscreen}"
exec "$@"
fi

if ! which xauth >/dev/null; then
error "xauth command not found"
exit 3
# Required tools if we are using Xvfb
command -v mktemp >/dev/null 2>&1 || die "Required command not found: mktemp"
command -v xauth >/dev/null 2>&1 || die "Required command not found: xauth"
command -v mcookie >/dev/null 2>&1 || die "Required command not found: mcookie"

# Choose server number
if [ -z "$SERVERNUM" ]; then
SERVERNUM=99
if [ -n "$AUTO_SERVERNUM" ]; then
while [ -f "/tmp/.X${SERVERNUM}-lock" ]; do
SERVERNUM=$((SERVERNUM + 1))
[ "$SERVERNUM" -le 200 ] || die "Could not find free X server number"
done
fi
fi

# tidy up after ourselves
trap clean_up EXIT
# Temp dir and Xauthority
XVFB_RUN_TMPDIR="$(mktemp -d)" || die "mktemp -d failed"
AUTHFILE="$XVFB_RUN_TMPDIR/Xauthority"
: >"$AUTHFILE" || die "Cannot create $AUTHFILE"

# If the user did not specify an X authorization file to use, set up a temporary
# directory to house one.
if [ -z "$AUTHFILE" ]; then
XVFB_RUN_TMPDIR="$(mktemp -d -t $PROGNAME.XXXXXX)"
# Create empty file to avoid xauth warning
AUTHFILE=$(tempfile -n "$XVFB_RUN_TMPDIR/Xauthority")
COOKIE="$(mcookie)" || die "mcookie failed"
if ! XAUTHORITY="$AUTHFILE" xauth -q add ":$SERVERNUM" MIT-MAGIC-COOKIE-1 "$COOKIE" \
2>>"${ERRORFILE:-/dev/stderr}"; then
die "xauth failed"
fi

# Start Xvfb.
MCOOKIE=$(mcookie)
tries=10
while [ $tries -gt 0 ]; do
tries=$(( $tries - 1 ))
XAUTHORITY=$AUTHFILE xauth source - << EOF >>"$ERRORFILE" 2>&1
add :$SERVERNUM $XAUTHPROTO $MCOOKIE
EOF
# handle SIGUSR1 so Xvfb knows to send a signal when it's ready to accept
# connections
trap : USR1
(trap '' USR1; exec Xvfb ":$SERVERNUM" $XVFBARGS $LISTENTCP -auth $AUTHFILE >>"$ERRORFILE" 2>&1) &
XVFBPID=$!

wait || :
if kill -0 $XVFBPID 2>/dev/null; then
# Start Xvfb
log "Starting Xvfb on :$SERVERNUM"
(
exec Xvfb ":$SERVERNUM" -auth "$AUTHFILE" $XVFBARGS
) >>"${ERRORFILE:-/dev/stderr}" 2>&1 &
XVFBPID=$!

# Wait for socket
i=0
while [ $i -lt 50 ]; do
if [ -S "/tmp/.X11-unix/X$SERVERNUM" ]; then
break
elif [ -n "$AUTONUM" ]; then
# The display is in use so try another one (if '-a' was specified).
SERVERNUM=$((SERVERNUM + 1))
SERVERNUM=$(find_free_servernum)
continue
fi
error "Xvfb failed to start" >&2
XVFBPID=
exit 1
if ! kill -0 "$XVFBPID" 2>/dev/null; then
die "Xvfb died during startup"
fi
i=$((i + 1))
sleep 0.05 2>/dev/null || sleep 1
done

# Start the command and save its exit status.
set +e
DISPLAY=:$SERVERNUM XAUTHORITY=$AUTHFILE "$@"
RETVAL=$?
set -e
[ -S "/tmp/.X11-unix/X$SERVERNUM" ] || die "Xvfb did not start"

# Return the executed command's exit status.
exit $RETVAL
# Run command
export DISPLAY=":$SERVERNUM"
export XAUTHORITY="$AUTHFILE"

# vim:set ai et sts=4 sw=4 tw=80:
log "Running: $*"
exec "$@"
Loading