Skip to content

Instantly share code, notes, and snippets.

@pgunn
Last active June 6, 2024 15:24
Show Gist options
  • Save pgunn/86c6dc47bd48bfec76364a421934a34d to your computer and use it in GitHub Desktop.
Save pgunn/86c6dc47bd48bfec76364a421934a34d to your computer and use it in GitHub Desktop.
#!/bin/bash
set -e
NEUTU_ENV=managed_neutu
NEUTU_WRAPPER_VERSION=84
NEWT_GIST_URL=https://gist.githubusercontent.com/pgunn/86c6dc47bd48bfec76364a421934a34d/raw/
NEWT_TEMPFILE=/tmp/new_newt
NEWT_PATH=$HOME/newt
# General arguments for whenever we do a "conda run"
CONDA_RUNARGS="--no-capture-output --live-stream"
CURL=curl
# If you really, really don't want to use mamba for some reason, set MAMBA=conda
#MAMBA=mamba
MAMBA=conda
TRACE_POLICY=wasptrace.flatironinstitute.org:8000
POLICY_UUID=99aaaaa
URL_USERLIST=http://$TRACE_POLICY/api/node/$POLICY_UUID/users/keys
URL_USER_EXPAND=http://$TRACE_POLICY/api/node/$POLICY_UUID/users/key
# Pins.
# NeuTu and Neu3 release IDs don't always mirror each other, so we need separate pins.
PIN_NEUTU=0.9.9
PIN_NEUTHREE=0.9.10
#PIN_LIBDVID_CPP=0.3.post118
NEUTU_DEV_ENV=managed_dev_neutu
NEUTU_OLD_ENV=managed_old_neutu
NEUTU_DEBUG_ENV=managed_debug_neutu
DEVEL_ENV=neuclease
DEVEL_JUP_ENV=neuclease_jupyter
# Config stuff
NEWT_CONFIG=$HOME/.newtconfig
# Packages newt uses and always needs
#NEWT_ALWAYS_INSTALL_BASE="mamba jq"
NEWT_ALWAYS_INSTALL_BASE="jq"
# Minimum acceptable version of newt is managed on a gist
NEWT_MINVERSION_GIST_URL=https://gist.githubusercontent.com/pgunn/a278e73ed5c4cbaf0ff80b6e9385fa63/raw/
#####################
# newt - Flatiron NeuTu wrapper
#
# This is designed to run on Linux or OSX, and should handle
# management and launching of NeuTu. This has a list of subcommands,
# but we want to keep it simple as:
# 1) shell programming is not maintainable, and
# 2) Linux and OSX have few guarantees between them in terms of
# package versioning or presence.
#
# We assume that "managed_neutu" is an environment this script owns and can
# do whatever it likes with.
#
# Dependencies:
# bash - Linux has 4.x, OSX has 3.x (because they don't like GPL)
# curl - Usually present by default on Linux and OSX
#################
# Find where Conda is and activate it in case the user's dotfiles didn't do that
if [ -d "$HOME/miniconda3" ]; then
CONDA_PATH="$HOME/miniconda3"
elif [ -d "$HOME/anaconda3" ]; then
CONDA_PATH="$HOME/anaconda3"
elif [ -d "$HOME/miniconda2" ]; then
CONDA_PATH="$HOME/miniconda2"
elif [ -d "$HOME/anaconda2" ]; then
CONDA_PATH="$HOME/anaconda2"
elif [ -d "$HOME/opt/miniconda3" ]; then
CONDA_PATH="$HOME/opt/miniconda3"
elif [ -d "$HOME/opt/anaconda3" ]; then
CONDA_PATH="$HOME/opt/anaconda3"
elif [ -d "$HOME/programs/anaconda3" ]; then
CONDA_PATH="$HOME/programs/anaconda3"
elif [ ! -z "$CONDA_EXE" ]; then
# Maybe actually the best way to do it?
CONDA_PATH=$(dirname $CONDA_EXE)/..
else
echo "Cannot find Miniconda or Anaconda in any of the standard places. Giving up."
exit 1
fi
# ensure that curl is installed and available in the PATH
[[ ! $(type -P "$CURL") ]] && echo "$CURL is not installed and it is a prerequisite for newt" && exit 1
if [ -f "$CONDA_PATH/etc/conda_path.sh" ]; then
. $CONDA_PATH/etc/conda_bash.sh
elif [ -f "$CONDA_PATH/etc/profile.d/conda.sh" ]; then
. $CONDA_PATH/etc/profile.d/conda.sh
fi
conda activate base
################
# Time check
#
# We would like to warn the user if they're trying to use neutu at a time when the server is either being backed up
# or will be soon. Backups start at 3am. This used to be a bigger concern, but we switched to a more efficient process
# sometime back so this warning is less important now
HOUR_USEAST=$(TZ=:America/New_York date +%H)
if [ ${HOUR_USEAST} -lt 5 ]; then
echo "*****************"
echo "* WARNING: the tracing server is backed up every night at 3am US-Eastern,"
echo "* and is briefly unavailable for a bit for that"
echo "* NeuTu will not work while the tracing server is down."
echo "* If you are active on it at that time, the server will disappear under you and"
echo "* some of your most recent work may be lost."
echo "* Caveat Operarius"
echo "*****************"
fi
################
# Handle usernames
#
# This is fairly ugly stuff that attempts to vet users trying to use NeuTu to make sure they're known, and
# if their username isn't the one they're primarily using on the system, to tell NeuTu what their preferred
# username is. See
# https://paper.dropbox.com/doc/DVID-data-storage--AvlApU0DR_Q9m8lUqVRymd4VAg-OQjxfKbmrCqVXY9dSyVLH
# for the dynamic policy side of this.
# Not proud of this tr-based parsing - we just delete json characters until bash's list constructor is happy
ALL_USERS=($($CURL $URL_USERLIST 2>/dev/null | tr -d "\"][" | tr ',' ' '))
if [ "${#ALL_USERS[@]}" -lt 1 ]; then
echo "Could not retrieve user list; the tracing DVID server may be down (possibly nightly backups if it is after 2AM US-Eastern)"
echo "Please contact pgunn if you see this message during normal times of the day"
exit 1
fi
# If we were on Bash 4.x I'd use an associative array for this.
for u in "${ALL_USERS[@]}"; do
ALTS_FOR_THIS_USER=($($CURL $URL_USER_EXPAND/$u 2>/dev/null | tr -d "\"][" | tr ',' ' '))
for a in "${ALTS_FOR_THIS_USER[@]}"; do
eval "ALIAS_$a"='$u'
done
done
# The regex max of the serialised form is probably the worst part of this part of the code.
# TODO: Consider refactoring so username is always explicitly provided, to simplify any special
# per-user logic
EXTRA_USERNAME=""
ALIAS_SYMBOL="ALIAS_$USER"
if [[ " ${ALL_USERS[@]} " =~ " ${USER} " ]]; then
echo "NeuTu Username: ${USER}"
elif [ ! -z "${!ALIAS_SYMBOL}" ]; then
echo "Looking up alias for $USER"
EXTRA_USERNAME="user:${!ALIAS_SYMBOL}"
echo "NeuTu Username: ${!ALIAS_SYMBOL}"
else
echo "Unrecognised username, please contact Pat to be added to the userlist"
exit 1
fi
################
# TODO: Refactor these to reduce redundancy
launch_neutu () {
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu.app/Contents/MacOS/neutu
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu
fi
echo "Launching neutu as: $NEUTU_BIN $EXTRA_USERNAME"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_ENV $NEUTU_BIN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_neuthree () {
if [ "$(uname)" == "Darwin" ]; then
# Neu3 is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neu3.app/Contents/MacOS/neu3
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neu3
fi
echo "******* WARNING ******"
echo "neu3 launched in non-guided mode will not set a cleave server"
echo "If you want to use a cleave server, please use rlaunch3"
echo "**********************"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_ENV $NEUTU_BIN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_guided_local_neutu() {
generate_neutu_localconfig_from_argtwo_and_argthree
echo "Generated configs"
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu.app/Contents/MacOS/neutu
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu
fi
echo "Launching neutu as: $NEUTU_BIN $EXTRA_USERNAME --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_ENV $NEUTU_BIN --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_guided_localish_neutu() {
generate_neutu_localishconfig_from_args
echo "Generated configs"
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu.app/Contents/MacOS/neutu
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu
fi
echo "Launching neutu as: $NEUTU_BIN $EXTRA_USERNAME --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_ENV $NEUTU_BIN --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_guided_devel_neutu() {
generate_neutu_config_from_argtwo
echo "Generated configs"
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_DEV_ENV/bin/neutu.app/Contents/MacOS/neutu
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_DEV_ENV/bin/neutu
fi
echo "Launching neutu as: $NEUTU_BIN $EXTRA_USERNAME --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_DEV_ENV $NEUTU_BIN --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_guided_debug_neutu() {
generate_neutu_config_from_argtwo
echo "Generated configs"
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_DEBUG_ENV/bin/neutu_d.app/Contents/MacOS/neutu_d
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_DEBUG_ENV/bin/neutu_d
fi
echo "Launching neutu as: $NEUTU_BIN $EXTRA_USERNAME --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_DEBUG_ENV $NEUTU_BIN --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_guided_neutu () {
generate_neutu_config_from_argtwo
echo "Generated configs"
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu.app/Contents/MacOS/neutu
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu
fi
echo "Launching neutu as: $NEUTU_BIN $EXTRA_USERNAME --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_ENV $NEUTU_BIN --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_guided_neuthree () {
# TODO: Also retrieve the cleave server and set env vars appropriately
generate_neutu_config_from_argtwo
URL_GET_CLEAVE_SERVER=http://$TRACE_POLICY/api/node/$AUTOREPO:main/fi_info/key/cleave_server
set +e
POTENTIAL_CLEAVE_SERVER=$($CURL $URL_GET_CLEAVE_SERVER 2>/dev/null | tr -d "\"" | grep -v "could not find" | grep -v "not found")
set -e
if [ -z "$POTENTIAL_CLEAVE_SERVER" ]; then
echo "Could not find cleave server for repo $AUTOREPO"
else
export NEU3_CLEAVE_SERVER=http://$POTENTIAL_CLEAVE_SERVER
echo "Set cleave server to http://$POTENTIAL_CLEAVE_SERVER"
fi
echo "Generated configs"
if [ "$(uname)" == "Darwin" ]; then
# Neu3 is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neu3.app/Contents/MacOS/neu3
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neu3
fi
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_ENV $NEUTU_BIN --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_viewmode_neutu() {
# args:
# $1 is specimen
generate_view_config $1
echo "Generated configs"
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu.app/Contents/MacOS/neutu
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu
fi
echo "Launching neutu as: $NEUTU_BIN $EXTRA_USERNAME --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN"
echo "Logs will have the $$ identifier"
conda run $CONDA_RUNARGS -n $NEUTU_ENV $NEUTU_BIN --load config:/tmp/neu_${USER}/neu_wrapper.json dname:AUTOGEN $EXTRA_USERNAME 2>~/log-newt-$$.err >~/log-newt-$$.out
}
launch_the_skeletons() {
# args:
# $1 is the repospec
# $2 is either:
# numeric value of the bodyid we want to skeletonise
# text file ending in .txt containing multiple bodyids to skeletonise
# (neutu handles all the difference between those uses, we just pass it along and hope it does the right thing)
#
# With this usage, we don't need to generate any config files; all the config information is passed to neutu from the CLI; we just need to
# generate that config string and arrange for neutu to be launched.
REPO=$1
BODYSPEC=$2
if [ "$(uname)" == "Darwin" ]; then
# NeuTu is packaged differently on OSX to fit the bundle format for that platform
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu.app/Contents/MacOS/neutu
else # Assume Linux
NEUTU_BIN=$CONDA_PATH/envs/$NEUTU_ENV/bin/neutu
fi
# TODO: This chunk of code exists elsewhere in this script and should be genericised
TRACE_ONE='wasptrace.flatironinstitute.org' # Look here first
TRACE_TWO='wasptrace2.flatironinstitute.org' # If not there, then here
TRACE_THR='wasptrace3.flatironinstitute.org' # If not there, then here
TRACING_SERVER=$TRACE_ONE
if [ $(repo_exists_on_server $TRACING_SERVER $REPO) != '200' ]; then
echo "Trace fallback"
TRACING_SERVER=$TRACE_TWO
if [ $(repo_exists_on_server $TRACING_SERVER $REPO) != '200' ]; then
TRACING_SERVER=$TRACE_THR
if [ $(repo_exists_on_server $TRACING_SERVER $REPO) != '200' ]; then
echo "Trace fallback failed: $TRACING_SERVER failed or does not have $REPO"
exit 1
fi
fi
fi
SKELCONFIG="http://$TRACING_SERVER?uuid=$REPO:main\&segmentation=labels"
echo "Launching skeletonization mode with IDs=$BODYSPEC CONFIG=$SKELCONFIG"
if [ ! -d "/tmp/neu_{$USER}" ]; then
mkdir "/tmp/neu_{$USER}"
fi
SKELSCRIPT=/tmp/neu_${USER}/skel_launcher.sh
echo "#!/bin/bash" > $SKELSCRIPT
echo "neutu --command --skeletonize --bodyid $BODYSPEC $SKELCONFIG" >> $SKELSCRIPT
chmod 755 $SKELSCRIPT
conda run $CONDA_RUNARGS -n $NEUTU_ENV $SKELSCRIPT
}
#################
# Config generation
#
# TODO: A lot of this code is duplicated and should be condensed, maybe by changing some of the code blocks into their own functions
# Real full unification of the functions would be hard (different arguments, which are hard to do conditionally in a non-confusing
# way, but if the config generation uses helper functions each one could be quite short and the differences would be more apparent.
generate_neutu_config_from_argtwo () {
# This is the main codepath for launching neutu in newt
# generate the two stub json files needed to launch neutu/neu3 against that repo
# TODO If it took args, this would be sensible:
# $1 - Was a global called AUTOREPO, should just be REPO or UUID or similar
mkdir -p /tmp/neu_${USER}
rm -f /tmp/neu_${USER}/neu_wrapper.json /tmp/neu_${USER}/neu_gen.json
cat > /tmp/neu_${USER}/neu_wrapper.json <<EOCFGWRAPPER
{ "flyem": ["/tmp/neu_${USER}/neu_gen.json"] }
EOCFGWRAPPER
# Now with the easy part out of the way, we need to generate a correct neutu config for the
# repo living in $1. Next we pull the specimen from the repo identifier; with that,
# the rest we can hardcode because we have only two specimens and most of the config for both is
# static.
check_if_command_exists jq
SPECIMEN=$(get_specimen_id_for_repo $AUTOREPO)
if [ "$SPECIMEN" == "FAIL" ]; then
echo "Repo $AUTOREPO was found but not marked with manage_dvid_seg; could not identify specimen"
exit 1
fi
echo "Working with specimen $SPECIMEN"
resolve_config
if [ "$SPECIMEN" == "wasp1" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
elif [ "$SPECIMEN" == "wasp2" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
elif [ "$SPECIMEN" == "wasp3" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
elif [ "$SPECIMEN" == "wasp2a" ]; then
# This has always been a special case
GRAYSCALE="wasp2a"
IMAGEUUID="d3e5db172"
IMAGESERVER="waspem-dvid.flatironinstitute.org"
else
echo "Error: Failed to get specimen data for repo $AUTOREPO:main"
exit 1
fi
if [ "$LAUNCH_MODE" == "normal" ]; then
USE_UUID="$AUTOREPO:main"
elif [ "$LAUNCH_MODE" == "exact" ]; then
USE_UUID="$AUTOREPO"
else
echo "Unknown launch mode"
exit 1
fi
TRACE_ONE='wasptrace.flatironinstitute.org' # Look here first
TRACE_TWO='wasptrace2.flatironinstitute.org' # If not there, then here
TRACE_THR='wasptrace3.flatironinstitute.org' # If not there, then here
TRACING_SERVER=$TRACE_ONE
# time for sanity checks and fallbacks
if [ $(repo_exists_on_server $IMAGESERVER $IMAGEUUID) != '200' ]; then
echo "Image server $IMAGESERVER may be down? NeuTu will not function"
exit 1
fi
if [ $(repo_exists_on_server $TRACING_SERVER $USE_UUID) != '200' ]; then
echo "Trace fallback"
TRACING_SERVER=$TRACE_TWO
if [ $(repo_exists_on_server $TRACING_SERVER $USE_UUID) != '200' ]; then
TRACING_SERVER=$TRACE_THR
if [ $(repo_exists_on_server $TRACING_SERVER $USE_UUID) != '200' ]; then
echo "Trace fallback failed: $TRACING_SERVER failed or does not have $USE_UUID"
exit 1
fi
fi
fi
# Remember: When you don't quote your HEREDOC end marker, you get string interpolation.
cat > /tmp/neu_${USER}/neu_gen.json <<EOCFGNEUGEN
{
"dvid repo": [{"gray_scale": "$GRAYSCALE","name": "AUTOGEN", "roi_list": [], "roi": "${ROI+$ROI}", "multires_tile": "", "port": 8000, "synapse": "synapses", "host": "$TRACING_SERVER", "body_label": "labels", "uuid": "$USE_UUID", "@source": { "multires_tile": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" }, "gray_scale": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" } }, "label_max_zoom": 0, "background": 255, "label_block": "labels", "multires_tile_config": { "$TILES": { "low_quality": false } }, "grayscale_max_zoom": 0, "proofreading": true, "supervised": true, "librarian": "$TRACING_SERVER:$LIBPORT", "default": false}]
}
EOCFGNEUGEN
}
generate_neutu_localconfig_from_argtwo_and_argthree () {
# Does not talk to the policy repo the same way, because this is for segmentations that run on localhost
# generate the two stub json files needed to launch neutu/neu3 against that repo
# TODO If it took args, this would be sensible:
# $1 - Was a global called AUTOREPO, should just be REPO or UUID or similar
# $2 - Was a global called SPEC
mkdir -p /tmp/neu_${USER}
rm -f /tmp/neu_${USER}/neu_wrapper.json /tmp/neu_${USER}/neu_gen.json
cat > /tmp/neu_${USER}/neu_wrapper.json <<EOLCFGWRAPPER
{ "flyem": ["/tmp/neu_${USER}/neu_gen.json"] }
EOLCFGWRAPPER
# Now with the easy part out of the way, we need to generate a correct neutu config for the
# repo living in $1. Next we pull the specimen from the repo identifier; with that,
# the rest we can hardcode because we have only two specimens and most of the config for both is
# static.
check_if_command_exists jq
echo "Building localconfig for specimen [$SPEC]"
SPECIMEN=$SPEC
echo "Working with specimen $SPECIMEN"
resolve_config
if [ "$SPECIMEN" == "wasp1" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
elif [ "$SPECIMEN" == "wasp2" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
elif [ "$SPECIMEN" == "wasp3" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
elif [ "$SPECIMEN" == "wasp2a" ]; then
GRAYSCALE="wasp2a"
IMAGEUUID="d3e5db172"
IMAGESERVER="waspem-dvid.flatironinstitute.org"
else
echo "Error: Failed to get specimen data for repo $AUTOREPO:main"
exit 1
fi
if [ "$LAUNCH_MODE" == "normal" ]; then
USE_UUID="$AUTOREPO:main"
elif [ "$LAUNCH_MODE" == "exact" ]; then
USE_UUID="$AUTOREPO"
else
echo "Unknown launch mode"
exit 1
fi
# Remember: When you don't quote your HEREDOC end marker, you get string interpolation.
cat > /tmp/neu_${USER}/neu_gen.json <<EOCFGNEULGEN
{
"dvid repo": [{"gray_scale": "$GRAYSCALE","name": "AUTOGEN", "roi_list": [], "roi": "${ROI+$ROI}", "multires_tile": "", "port": 8000, "synapse": "synapses", "host": "localhost:8000", "body_label": "labels", "uuid": "$USE_UUID", "@source": { "multires_tile": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" }, "gray_scale": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" } }, "label_max_zoom": 0, "background": 255, "label_block": "labels", "multires_tile_config": { "$TILES": { "low_quality": false } }, "grayscale_max_zoom": 0, "proofreading": true, "supervised": true, "librarian": "", "default": false}]
}
EOCFGNEULGEN
}
generate_neutu_localishconfig_from_args () {
# This is used to launch neutu in a configuration used for testing segmentation running on a system
# that's not our normal segmentation hosts. It's very rarely useful.
# generate the two stub json files needed to launch neutu/neu3 against that repo
# TODO If it took args, this would be sensible (calling code needs to flip order around):
# $1 - Was a global called AUTOREPO, should just be REPO or UUID or similar
# $2 - Was a global called SEG_HOST, holding hostname of alternate segmentation server
# $3 - Was a global called SPEC, holding specimen id
mkdir -p /tmp/neu_${USER}
rm -f /tmp/neu_${USER}/neu_wrapper.json /tmp/neu_${USER}/neu_gen.json
cat > /tmp/neu_${USER}/neu_wrapper.json <<EOLCFGWRAPPER
{ "flyem": ["/tmp/neu_${USER}/neu_gen.json"] }
EOLCFGWRAPPER
# Now with the easy part out of the way, we need to generate a correct neutu config for the
# repo living in $1. Next we pull the specimen from the repo identifier; with that,
# the rest we can hardcode because we have only two specimens and most of the config for both is
# static.
check_if_command_exists jq
echo "Building localconfig for specimen [$SPEC]"
SPECIMEN=$SPEC
echo "Working with specimen $SPECIMEN"
resolve_config
if [ "$SPECIMEN" == "wasp1" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
elif [ "$SPECIMEN" == "wasp2" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
elif [ "$SPECIMEN" == "wasp3" ]; then
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
elif [ "$SPECIMEN" == "wasp2a" ]; then
GRAYSCALE="wasp2a"
IMAGEUUID="d3e5db172"
IMAGESERVER="waspem-dvid.flatironinstitute.org"
else
echo "Error: Failed to get specimen data for repo $AUTOREPO:main"
exit 1
fi
if [ "$LAUNCH_MODE" == "normal" ]; then
USE_UUID="$AUTOREPO:main"
elif [ "$LAUNCH_MODE" == "exact" ]; then
USE_UUID="$AUTOREPO"
else
echo "Unknown launch mode"
exit 1
fi
# Remember: When you don't quote your HEREDOC end marker, you get string interpolation.
cat > /tmp/neu_${USER}/neu_gen.json <<EOCFGNEULGEN
{
"dvid repo": [{"gray_scale": "$GRAYSCALE","name": "AUTOGEN", "roi_list": [], "roi": "${ROI+$ROI}", "multires_tile": "", "port": 8000, "synapse": "synapses", "host": "$SEG_HOST:8000", "body_label": "labels", "uuid": "$USE_UUID", "@source": { "multires_tile": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" }, "gray_scale": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" } }, "label_max_zoom": 0, "background": 255, "label_block": "labels", "multires_tile_config": { "$TILES": { "low_quality": false } }, "grayscale_max_zoom": 0, "proofreading": true, "supervised": true, "librarian": "", "default": false}]
}
EOCFGNEULGEN
}
generate_view_config () {
# This is used for the "./newt view wasp3"
# command and similar, used to just view image stacks with no (real) segmentation loaded.
#
# generate the two stub json files needed to launch neutu/neu3 against that repo
# args:
# $1 is specimen
SPECIMEN=$1
mkdir -p /tmp/neu_${USER}
rm -f /tmp/neu_${USER}/neu_wrapper.json /tmp/neu_${USER}/neu_gen.json
cat > /tmp/neu_${USER}/neu_wrapper.json <<EOCFGWRAPPER
{ "flyem": ["/tmp/neu_${USER}/neu_gen.json"] }
EOCFGWRAPPER
# Now with the easy part out of the way, we need to generate a correct neutu config for the
# repo living in $1. Next we pull the specimen from the repo identifier; with that,
# the rest we can hardcode because we have only two specimens and most of the config for both is
# static.
check_if_command_exists jq
echo "Working with specimen $SPECIMEN"
resolve_config
echo "Building view mode for specimen $SPECIMEN"
if [ "$SPECIMEN" == "wasp1" ]; then
USE_UUID="98aaaa"
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP1_IMGSET)
elif [ "$SPECIMEN" == "wasp2" ]; then
USE_UUID="98bbbb"
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP2_IMGSET)
elif [ "$SPECIMEN" == "wasp3" ]; then
USE_UUID="98dddd"
GRAYSCALE=$(instance_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGEUUID=$(repo_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
IMAGESERVER=$(server_for_specimen_imageset $SPECIMEN $WASP3_IMGSET)
elif [ "$SPECIMEN" == "wasp2a" ]; then
USE_UUID="98cccc"
GRAYSCALE="wasp2a"
IMAGEUUID="d3e5db172"
IMAGESERVER="waspem-dvid.flatironinstitute.org"
else
echo "Error: Failed to get specimen data for view mode"
exit 1
fi
# Remember: When you don't quote your HEREDOC end marker, you get string interpolation.
cat > /tmp/neu_${USER}/neu_gen.json <<EOCFGNEUGEN
{
"dvid repo": [{"gray_scale": "$GRAYSCALE","name": "AUTOGEN", "roi_list": [], "roi": "${ROI+$ROI}","multires_tile": "", "port": 8000, "synapse": "synapses", "host": "wasptrace.flatironinstitute.org", "body_label": "labels", "uuid": "$USE_UUID", "@source": { "multires_tile": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" }, "gray_scale": { "port": 80, "host": "$IMAGESERVER", "uuid": "$IMAGEUUID" } }, "label_max_zoom": 0, "background": 255, "label_block": "labels", "grayscale_max_zoom": 0, "proofreading": true, "supervised": true, "librarian": "wasptrace.flatironinstitute.org:$LIBPORT", "default": false}]
}
EOCFGNEUGEN
}
######################
# The following are conceptually similar to fivol.py:get_imageconfigs_for_specimen()
#
# They're less general because shell programming is more awkward about data representations
# available (shell programming is terrible, particularly if you're trying to be portable)
summarise_imagesets_for_specimen() {
# This was originally intended to return the imagesets for a specimen in a convenient format
# for later parsing, but bash is not good at that kind of thing. Recycled into something that will
# tell users what their imageset options are for a given specimen, for use by the config argument with
# no subarguments.
SPECIMEN=$1
URL_ISETLIST=http://$TRACE_POLICY/api/node/$POLICY_UUID/specimen_$SPECIMEN/keys
IMAGESETS=($($CURL $URL_ISETLIST 2>/dev/null | tr -d "\"][" | tr ',' ' '))
if [ "${#IMAGESETS[@]}" -lt 1 ]; then
echo "I was unable to find any imagesets for the requested specimen, which should be something like wasp1, wasp2, wasp2a, or similar"
exit 1
fi
printf "\t\t%s\n" "${IMAGESETS[@]}"
}
repo_for_specimen_imageset() {
SPECIMEN=$1
IMAGESET=$2
URL_ISETINFO=http://$TRACE_POLICY/api/node/$POLICY_UUID/specimen_$SPECIMEN/key/$IMAGESET
REPO=($($CURL $URL_ISETINFO 2>/dev/null | jq '.repo' | tr -d "\"][" ))
echo $REPO
}
server_for_specimen_imageset() {
# The port is in there too, but I'm comfortable hardcoding that for now and "cut"ting it out
SPECIMEN=$1
IMAGESET=$2
URL_ISETINFO=http://$TRACE_POLICY/api/node/$POLICY_UUID/specimen_$SPECIMEN/key/$IMAGESET
# the retrieval gets something like "http://waspem-dvid.flatironinstitute.org:8000"
# so we need to get past the slashes and before the colon
SAP=($($CURL $URL_ISETINFO 2>/dev/null | jq '.server' | cut -d/ -f3 | cut -d: -f1 ))
echo $SAP
}
instance_for_specimen_imageset() {
SPECIMEN=$1
IMAGESET=$2
URL_ISETINFO=http://$TRACE_POLICY/api/node/$POLICY_UUID/specimen_$SPECIMEN/key/$IMAGESET
INST=($($CURL $URL_ISETINFO 2>/dev/null | jq '.instance' | tr -d '"' ))
echo $INST
}
######################
# Checking DVID servers for things
#
# This is used for fallbacks and sanity checks
repo_exists_on_server() {
# If you hit the /info endpoint of a real repo, you get a 200. Otherwise you get a 400. This is a reliable way to see if a repo is present on a DVID server (so far).
SERVER=$1
REPO=$2
URL_CHECK=http://$SERVER:8000/api/repo/$REPO/info
RESPONSE=($($CURL -s -o /dev/null -I -w "%{http_code}" $URL_CHECK))
echo $RESPONSE
}
get_specimen_id_for_repo() {
# Reliably, through fallback, identify the specimen for a repo or give the user a good error message
REPO=$1
TRY1=wasptrace.flatironinstitute.org # FIXME move this out to a shared list
TRY2=wasptrace2.flatironinstitute.org
if [ $(repo_exists_on_server $TRY1 $REPO) == '200' ]; then # first server, like most repos
if [ "$LAUNCH_MODE" == "exact" ]; then
URL_INFO_SPECIMEN=http://$TRY1:8000/api/node/$AUTOREPO/fi_info/key/specimen
else
URL_INFO_SPECIMEN=http://$TRY1:8000/api/node/$AUTOREPO:main/fi_info/key/specimen
fi
SPECIMEN=$($CURL $URL_INFO_SPECIMEN 2>/dev/null | tr -d "\"")
echo $SPECIMEN
elif [ $(repo_exists_on_server $TRY2 $REPO) == '200' ]; then # second server, newer repos
if [ "$LAUNCH_MODE" == "exact" ]; then
URL_INFO_SPECIMEN=http://$TRY2:8000/api/node/$AUTOREPO/fi_info/key/specimen
else
URL_INFO_SPECIMEN=http://$TRY2:8000/api/node/$AUTOREPO:main/fi_info/key/specimen
fi
SPECIMEN=$($CURL $URL_INFO_SPECIMEN 2>/dev/null | tr -d "\"")
echo $SPECIMEN
else
echo "FAIL" # Because of bash call semantics, this isn't the right place to spit out a good error message; caller needs to do that.
fi
}
######################
# Config and defaults management
#
# Functions here manage having some builtin default settings that can be overwritten by a config
# file, as well as management of that config file. The ideal is that users don't themselves edit
# that file (and it might not be present). A newt config won't necessarily have an entry for all
# possible configs.
#
# A lot of the settings here are half-hardcoded and ugly because bash doesn't offer good data structures
# to hold things. If we could depend on Bash4, we'd have more options, but OSX will be on Bash3
# for the long haul (license issues).
# The port that the Librarian runs on is also unfortunately commonly a printer port, and so
# often is blocked by networking groups. As local configuration, we also expose the librarian on port 8443,
# which is less likely to be blocked, and we offer a user-tweakable config
DEFAULT_LIBPORT=9100
DEFAULT_WASP1_IMGSET=sch1
DEFAULT_WASP2_IMGSET=tyk1
DEFAULT_WASP3_IMGSET=three_clahe
OVERRODE_WASP1_IMGSET=false
OVERRODE_WASP2_IMGSET=false
OVERRODE_WASP3_IMGSET=false
OVERRODE_LIBPORT=false
resolve_config() {
# This reads a config file and resolves any overrides with the defaults, presenting the final versions
# of variables to other parts of the codebase.
LIBPORT=$DEFAULT_LIBPORT
WASP1_IMGSET=$DEFAULT_WASP1_IMGSET
WASP2_IMGSET=$DEFAULT_WASP2_IMGSET
WASP3_IMGSET=$DEFAULT_WASP3_IMGSET
if [ ! -f $NEWT_CONFIG ]; then
echo "Using default newt config"
else
echo "Parsing newt config to override some defaults"
# Next we'll temporarily turn off "exit on error" so we can handle errors better
set +e
# Begin the parsing. It should be easy to add new parsing this way.
# grep exits with nonzero return code if it can't find its search string in the file.
# we use that to look for an entry to decide if we want to override the current value.
grep LIBPORT= $NEWT_CONFIG >/dev/null
if [ $? -eq 0 ]; then
echo "Overriding librarian port"
LIBPORT=($(grep LIBPORT= $NEWT_CONFIG 2>/dev/null | cut -d= -f2))
OVERRODE_LIBPORT=true
fi
grep WASP1_IMGSET= $NEWT_CONFIG >/dev/null
if [ $? -eq 0 ]; then
WASP1_IMGSET=($(grep WASP1_IMGSET= $NEWT_CONFIG 2>/dev/null | cut -d= -f2))
OVERRODE_WASP1_IMGSET=true
fi
grep WASP2_IMGSET= $NEWT_CONFIG >/dev/null
if [ $? -eq 0 ]; then
WASP2_IMGSET=($(grep WASP2_IMGSET= $NEWT_CONFIG 2>/dev/null | cut -d= -f2))
OVERRODE_WASP2_IMGSET=true
fi
grep WASP3_IMGSET= $NEWT_CONFIG >/dev/null
if [ $? -eq 0 ]; then
WASP3_IMGSET=($(grep WASP3_IMGSET= $NEWT_CONFIG 2>/dev/null | cut -d= -f2))
OVERRODE_WASP3_IMGSET=true
fi
# Restore standard strict error handling
set -e
fi
}
set_config_item() {
# This creates a config file if it does not already exist, or rewrites it if it does so it has the requested
# config entry and value. It removes any existing entry that would set the value that it wants to set.
# The mechanism to do this is the OVERRODE_* set of variables.
#
# You *must* call resolve_config() before using this function.
#
# This is a bit clunky but it does the job with what bash can offer.
NEWKEY=$1
NEWVAL=$2
if [ "$NEWKEY" = "WASP1_IMGSET" ]; then
OVERRODE_WASP1_IMGSET=true
WASP1_IMGSET=$NEWVAL
elif [ "$NEWKEY" = "WASP2_IMGSET" ]; then
OVERRODE_WASP2_IMGSET=true
WASP2_IMGSET=$NEWVAL
elif [ "$NEWKEY" = "WASP3_IMGSET" ]; then
OVERRODE_WASP3_IMGSET=true
WASP3_IMGSET=$NEWVAL
elif [ "$NEWKEY" = "LIBPORT" ]; then
echo "Updating LIBPORT in config"
OVERRODE_LIBPORT=true
LIBPORT=$NEWVAL
else
echo "Failed to reset unknown value $NEWKEY"
exit 1
fi
rm -f $NEWT_CONFIG
if [ "$OVERRODE_WASP1_IMGSET" = true ]; then
echo "WASP1_IMGSET=$WASP1_IMGSET" >> $NEWT_CONFIG
fi
if [ "$OVERRODE_WASP2_IMGSET" = true ]; then
echo "WASP2_IMGSET=$WASP2_IMGSET" >> $NEWT_CONFIG
fi
if [ "$OVERRODE_WASP3_IMGSET" = true ]; then
echo "WASP3_IMGSET=$WASP3_IMGSET" >> $NEWT_CONFIG
fi
if [ "$OVERRODE_LIBPORT" = true ]; then
echo "LIBPORT=$LIBPORT" >> $NEWT_CONFIG
fi
}
display_all_config_and_options() {
# Display all known config items, and what's set as well as what the other options are.
# You must call resolve_config() before using this function
if [ "$OVERRODE_WASP1_IMGSET" = true ]; then
echo " WASP1_IMGSET (overridden)=$WASP1_IMGSET"
else
echo " WASP1_IMGSET (default)=$WASP1_IMGSET"
fi
echo " Options:"
summarise_imagesets_for_specimen wasp1
if [ "$OVERRODE_WASP2_IMGSET" = true ]; then
echo " WASP2_IMGSET (overridden)=$WASP2_IMGSET"
else
echo " WASP2_IMGSET (default)=$WASP2_IMGSET"
fi
echo " Options:"
summarise_imagesets_for_specimen wasp2
if [ "$OVERRODE_WASP3_IMGSET" = true ]; then
echo " WASP3_IMGSET (overridden)=$WASP3_IMGSET"
else
echo " WASP3_IMGSET (default)=$WASP3_IMGSET"
fi
echo " Options:"
summarise_imagesets_for_specimen wasp3
if [ "$OVERRODE_LIBPORT" = true ]; then
echo " LIBPORT (overridden)=$LIBPORT"
else
echo " LIBPORT (default)=$LIBPORT"
fi
echo " Options:"
echo " Any valid numeric TCP port value (but must match server config). Default is $DEFAULT_LIBPORT but 8443 is also supported."
}
######################
# misc/general
check_if_command_exists() {
# Please don't use this with arguments, as it might do something dangerous
COMMAND=$1
set +e
$1 --help 2>&1 >/dev/null
if [ $? -ne 0 ]; then
echo "newt needs the $1 utility but could not find it. Please run ./newt update-prereqs"
exit 1
fi
set -e
}
######################
# Main command handler
echo "This is newt version $NEUTU_WRAPPER_VERSION"
if [ "$1" == "launch" ]; then
export USE_SEQUENCER=yes
launch_neutu
elif [ "$1" == "rlaunch" ]; then
#################
# Check minimum version
#
# We now check a gist to make sure we're current enough on our "newt" version (not neutu version)
# to start up, and refuse to start if we're not.
# This obviously won't help if someone is using a version of newt that doesn't have this code, but
# we can at least make the future a better place.
#
# This will let us make breaking changes to the configuration more safely in the future.
#
# I would have liked to have had this check be elsewhere, but it's important that it not impact
# newt's ability to update itself!
NEWT_MIN_VERSION=$($CURL $NEWT_MINVERSION_GIST_URL 2>/dev/null)
if [ "$NEUTU_WRAPPER_VERSION" -lt "$NEWT_MIN_VERSION" ]; then
echo "\tYour version of newt (not NeuTu, just newt) is too old."
echo "\tPlease update it with:"
echo "./newt update-newt"
echo "\tYou do NOT need to do a ./newt update afterwards"
exit 1
fi
export USE_SEQUENCER=yes
# BEGIN ARGUMENT PARSING
if [ "$#" -eq 3 ]; then
ROI=$3
elif [ "$#" -lt 2 ]; then
echo "Usage: ./newt rlaunch 16d7 OPTIONAL_ROI_NAME"
exit 1
elif [ "$#" -gt 3 ]; then
echo "Usage: ./newt rlaunch 16d7 OPTIONAL_ROI_NAME"
exit 1
fi
if [ -z "$2" ]; then
echo "FATAL: Could not parse repo while generating configs"
exit 1
else
AUTOREPO=$2
fi
# END ARGUMENT PARSING
LAUNCH_MODE="normal"
launch_guided_neutu
elif [ "$1" == "rlaunch-exact" ]; then
# This option is like rlaunch, but the repo identifier is parsed literally,
# allowing the user to supply a bare UUID without :main being appended, or
# allowing them to add another label for UUID resolution
export USE_SEQUENCER=yes
# BEGIN ARGUMENT PARSING
if [ "$#" -eq 3 ]; then
ROI=$3
elif [ "$#" -lt 2 ]; then
echo "Usage: ./newt rlaunch-exact 16d7 OPTIONAL_ROI_NAME"
exit 1
elif [ "$#" -gt 3 ]; then
echo "Usage: ./newt rlaunch-exact 16d7 OPTIONAL_ROI_NAME"
exit 1
fi
if [ -z "$2" ]; then
echo "FATAL: Could not parse repo while generating configs"
exit 1
else
AUTOREPO=$2
fi
# END ARGUMENT PARSING
LAUNCH_MODE="exact"
launch_guided_neutu
elif [ "$1" == "rlaunch-dev" ]; then
# This is just like rlaunch, but with the "dev" install of neutu
# "dev" is just whatever version is current on flyem-forge, rather than our
# curated version
export USE_SEQUENCER=yes
# BEGIN ARGUMENT PARSING
if [ "$#" -eq 3 ]; then
ROI=$3
elif [ "$#" -lt 2 ]; then
echo "Usage: ./newt rlaunch-dev 16d7 OPTIONAL_ROI_NAME"
exit 1
elif [ "$#" -gt 3 ]; then
echo "Usage: ./newt rlaunch-dev 16d7 OPTIONAL_ROI_NAME"
exit 1
fi
if [ -z "$2" ]; then
echo "FATAL: Could not parse repo while generating configs"
exit 1
else
AUTOREPO=$2
fi
# END ARGUMENT PARSING
LAUNCH_MODE="normal"
launch_guided_devel_neutu
elif [ "$1" == "rlaunch-debug" ]; then
# This is just like rlaunch, but with the "debug" install of neutu, usually a
# debug build that Ting gave us
echo "Launching a debug version of neutu!!"
export USE_SEQUENCER=yes
# BEGIN ARGUMENT PARSING
if [ "$#" -eq 3 ]; then
ROI=$3
elif [ "$#" -lt 2 ]; then
echo "Usage: ./newt rlaunch-debug 16d7 OPTIONAL_ROI_NAME"
exit 1
elif [ "$#" -gt 3 ]; then
echo "Usage: ./newt rlaunch-debug 16d7 OPTIONAL_ROI_NAME"
exit 1
fi
if [ -z "$2" ]; then
echo "FATAL: Could not parse repo while generating configs"
exit 1
else
AUTOREPO=$2
fi
# END ARGUMENT PARSING
LAUNCH_MODE="normal"
launch_guided_debug_neutu
elif [ "$1" == "rlaunch-local" ]; then
# This is intended for debugging alternative segmentation stacks running on the local
# system. It is not compatible with ROIs (not for any particular reason, but I doubt we'll
# ever care to do that kind of debugging)
export USE_SEQUENCER=yes
# BEGIN ARGUMENT PARSING
if [ "$#" -ne 3 ]; then
echo "Sample Usage: ./newt rlaunch-local 16d7 wasp1"
exit 1
fi
if [ -z "$2" ]; then
echo "FATAL: Could not parse repo while generating configs"
exit 1
else
AUTOREPO=$2
fi
if [ -z "$3" ]; then
echo "FATAL: Could not parse specimen while generating configs"
exit 1
else
SPEC=$3
fi
# END ARGUMENT PARSING
LAUNCH_MODE="normal"
launch_guided_local_neutu
elif [ "$1" == "rlaunch-localish" ]; then
# This is intended for debugging alternative segmentation stacks running on the local(ish)
# system. Almost the same semantics as rlaunch-local but you also have a hostname in there
export USE_SEQUENCER=yes
# BEGIN ARGUMENT PARSING
if [ "$#" -ne 4 ]; then
echo "Sample Usage: ./newt rlaunch-localish hostname 16d7 wasp1"
exit 1
fi
if [ -z "$2" ]; then
echo "FATAL: You must provide a hostname"
exit 1
else
SEG_HOST=$2
fi
if [ -z "$3" ]; then
echo "FATAL: Could not parse repo while generating configs"
exit 1
else
AUTOREPO=$3
fi
if [ -z "$4" ]; then
echo "FATAL: Could not parse specimen while generating configs"
exit 1
else
SPEC=$4
fi
# END ARGUMENT PARSING
LAUNCH_MODE="normal"
launch_guided_localish_neutu
elif [ "$1" == "launchnos" ]; then
LAUNCH_MODE="normal"
launch_neutu
elif [ "$1" == "launch3" ]; then
LAUNCH_MODE="normal"
export USE_SEQUENCER=yes
launch_neuthree
elif [ "$1" == "rlaunch3" ]; then
LAUNCH_MODE="normal"
export USE_SEQUENCER=yes
if [ -z "$2" ]; then
echo "FATAL: Could not parse repo while generating configs"
exit 1
else
AUTOREPO=$2
fi
launch_guided_neuthree
elif [ "$1" == "view" ]; then
if [ -z "$2" ]; then
echo "FATAL: Could not parse specimenid while generating configs: use wasp1, wasp2, or wasp2a"
exit 1
fi
# $2 is specimen, like wasp1, wasp2...
launch_viewmode_neutu $2
elif [ "$1" == "skel" ]; then
# Launch neutu in command:skeletonization mode, to generate and upload skeletons to DVID
if [ "$#" -ne 3 ]; then
echo "Sample usage: ./newt skel 020cc:main 12501"
exit 1
fi
launch_the_skeletons $2 $3
elif [ "$1" == "devel" ]; then
conda deactivate
conda clean -y --all
$MAMBA env remove -n $DEVEL_ENV || true # Allow this to fail - old environment might not exist
$MAMBA create -y -n $DEVEL_ENV -c flyem-forge -c conda-forge neuclease "numpy>=1.26.0,<2.0.0" "pandas>=2.2.0" python
echo "Neuclease development environment created"
elif [ "$1" == "devel-jupyter" ]; then
conda deactivate
conda clean -y --all
$MAMBA env remove -n $DEVEL_JUP_ENV || true # Allow this to fail - old environment might not exist
$MAMBA create -y -n $DEVEL_JUP_ENV -c flyem-forge -c conda-forge neuclease "numpy>=1.26.0,<2.0.0" "pandas>=2.2.0" python jupyter
echo "Neuclease development environment with jupyter created"
elif [ "$1" == "update" ]; then
conda install -y -n base -c conda-forge $NEWT_ALWAYS_INSTALL_BASE
echo "Removing old environment"
conda deactivate
echo "I am cleaning your conda install. This may take a bit the first time"
conda clean -y --all
$MAMBA env remove -n $NEUTU_ENV || true # Allow this to fail - old environment might not exist
echo "Creating new environment"
# XXX Temporary reversion
$MAMBA create -y -n $NEUTU_ENV -c flyem-forge -c conda-forge neutu-develop=$PIN_NEUTU neu3-develop=$PIN_NEUTHREE
#$MAMBA create -y -n $NEUTU_ENV -c flyem-forge -c conda-forge neutu-develop=$PIN_NEUTU neu3-develop=$PIN_NEUTHREE libdvid-cpp=$PIN_LIBDVID_CPP
echo "New environment created"
elif [ "$1" == "update-dev" ]; then
conda install -y -n base -c conda-forge $NEWT_ALWAYS_INSTALL_BASE
echo "Removing old dev environment"
conda deactivate
echo "I am cleaning your conda install. This may take a bit the first time"
conda clean -y --all
$MAMBA env remove -n $NEUTU_DEV_ENV || true # Allow this to fail - old environment might not exist
echo "Creating new dev env..."
# This lone pin may or may not cause problems in the future, but some installs seem oddly insistent on delivering a version of libdvid-cpp
# that as-of-this-writing does not work with any released version of neutu. This code will likely need to change in the future.
$MAMBA create -y -n $NEUTU_DEV_ENV -c flyem-forge -c conda-forge neutu-develop neu3-develop
echo "New dev environment created"
elif [ "$1" == "update-debug" ]; then
echo "This command not currently supported"
exit 1
conda install -y -n base -c conda-forge $NEWT_ALWAYS_INSTALL_BASE
echo "Removing old debug environment"
conda deactivate
echo "I am cleaning your conda install. This may take a bit the first time"
conda clean -y --all
$MAMBA env remove -n $NEUTU_DEBUG_ENV || true # Allow this to fail - old environment might not exist
echo "Creating new debug env..."
# This lone pin may or may not cause problems in the future, but some installs seem oddly insistent on delivering a version of libdvid-cpp
# that as-of-this-writing does not work with any released version of neutu. This code will likely need to change in the future.
$MAMBA create -y -n $NEUTU_DEBUG_ENV -c tingzhao -c flyem-forge -c conda-forge neutu-debug
echo "New debug environment created!!"
elif [ "$1" == "update-prereqs" ]; then
conda install -y -n base -c conda-forge $NEWT_ALWAYS_INSTALL_BASE
elif [ "$1" == "update-newt" ]; then
echo "Updating newt"
rm -f $NEWT_TEMPFILE
$CURL $NEWT_GIST_URL -o $NEWT_TEMPFILE
chmod 755 $NEWT_TEMPFILE
echo "Performing self-update of newt manager"
/bin/mv $NEWT_TEMPFILE $NEWT_PATH && exit 0
elif [ "$1" == "info" ]; then
echo "NeuTu is version $(conda list -n managed_neutu neutu-develop | grep neutu-develop | tr -s ' ' | cut -d" " -f2)"
echo "Latest NeuTu in flyem-forge is version $(conda search -c flyem-forge neutu-develop | tail -1 | tr -s ' ' | cut -d" " -f2)"
if [ "$(uname)" == "Darwin" ]; then
echo "Your system has $(hwprefs cpu_count) cores and $(hwprefs memory_size) memory"
else # Assume Linux
echo "Your system has $(lscpu -p -y | grep -v "^#" | wc -l) cores and $(free --giga | grep Mem | tr -s ' ' | cut -d" " -f2)G memory"
fi
#echo "Latest NeuTu in dev (not available via this tool) is version $(conda search -c tingzhao neutu-develop | tail -1 | tr -s ' ' | cut -d" " -f2)"
elif [ "$1" == "config" ]; then
resolve_config
echo "You can use this subcommand to view the current config, or to change it"
if [ "$#" -eq 1 ]; then
echo "Config:"
display_all_config_and_options
echo "To set a value, do something like ./newt config WASP2_IMGSET tch1"
else
resolve_config
set_config_item $2 $3
echo "I will parse further args to set config options"
fi
else
echo "Usage: newt COMMAND"
echo "Commands:"
echo -e "\trlaunch REPO OPTIONAL_ROI -- Launch neutu against named repo (do not provide :main)"
echo -e "\trlaunch-exact REPO OPTIONAL_ROI -- Launch neutu against exact UUID (mostly intended for historical view)"
echo -e "\tlaunch3 -- Launch neu3"
echo -e "\trlaunch3 REPO -- Launch neu3 against named repo (do not provide :main)"
echo -e "\tskel REPO BODYSPEC -- Generate and upload skeletons for either a provided numeric body, or for all bodies found in a textfile (that must end in .txt)"
echo -e "\tupdate -- Update/install neutu"
echo -e "\tupdate-newt -- Update the newt wrapper itself"
echo -e "\tdevel -- Set up a neuclease conda environment"
echo -e "\tdevel-jupyter -- Set up a neuclease conda environment with Jupyter"
echo -e "\tinfo -- Show info on your system"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment