#!/bin/bash

# file: $ISIP_IFC/login/shell_bashrc.sh
#
# this is the standard .bashrc file.
# a user should execute this file at the top of their personal
# bashrc file.
#
# revision history:
#
# (20240927) ER: explicitly set qt plugin path for pyqt6 in nedc environment
# (20240613) JP: removed some libraries from the default environment
# (20240229) JP: added an fd alias that combines sd and d
# (20230304) LR: added gcc-arm to the path
# (20220525) JJ: added QuPath to the path
# (20220209) JJ: updated ASAP path to match consistent directory structure
# (20220204) JJ: added ASAP to the path
# (20220118) JP: switched the functions d and f to aliases
# (20210824) DR: remove conda libs from LD path
# (20210708) DR: explicitly activate the `nedc` Conda env and adjust flags
# (20210608) DR: added back CUDA_VISIBLE_DEVICES if Slurm hasn't set it to GPUs
# (20210216) JP: decoupled the NFCs from the IFCs
# (20210203) JP: removed the qmn alias
# (20210203) LL: fixed the f alias for the Mac
# (20210202) JP: cleaned up a few things
# (20210124) LL: updated PATH, shopt -s direxpand, d, and f for mac
# (20210101) LL: removed CLASSPATH, matlab and perl configure sections
# (20200929) LB: cleaned the PATH and LD_LIBRARY_PATH to match tools/generic
# (20200922) SJ: removed torch from PATH and LD_LIBRARY_PATH
# (20200922) SJ: removed cudnn lib from LD_LIBRARY_PATH
# (20200922) SJ: removed anaconda2 lib from LD_LIBRARY_PATH
# (20200921) SJ: added conda init lines and removed anaconda2 from path 
# (20200914) LB: added cuda to path and library
# (20200731) DR: added CPAN path for Perl modules
# (20200721) DR: removed CUDA_VISIBLE_DEVICES setting (managed by Slurm)
# (20200612) DR: removed slurm from the env
# (20200603) JP: added openslide to the official env
# (20200517) JP: added compilation variables to point to boost
# (20200112) SJ: added emacs to the path
# (20200111) JP: removed htk; add sbin to the path; organized the path
# (20191226) JP: removed references to Kaldi
# (20191226) SJ: added lib64 to LD path (fixes g_date_copy error)
# (20190523) SJ: removed rclone from the path
# (20190522) SJ: added rclone to the path
# (20180328) TD: added valgrind to the path
# (20180222) JP: added lshw to the path
# (20180119) TD: removed the unset of the DISPLAY variable
# (20180118) TD: removed a lib in $LD_LIBRARY_PATH due to versioning issues
# (20180118) TD: set var MKL_THREADING_LAYER to GNU to use 2018 theano
# (20180117) JP: added an unset of the DISPLAY variable
# (20180116) TD: added open-cv to $LD_LIBRARY_PATH
# (20180821) CC: added current direcotry to $PYTHONPATH for slurm
# (20180817) CC: set CUDA_VISIBLE_DEVICES to prevent unauthorized gpu usage
# (20180718) CC: added Anaconda's MKL package to $LD_LIBRARY_PATH (for theano)
# (20180711) CC: added slurm to $PATH
# (20180511) CC: added QuPath to $PATH
# (20180410) JP: converted the spelling interface to ispell
# (20180308) CC: added cudnn to LD_LIBRARY_PATH
# (20180307) CC: fixed typo in LIBRARY_PATH
# (20180306) JP: removed /research from the directory tree
# (20180228) CC: added cuddnn to the CPATH and LIBRARY_PATH
# (20180228) CC: updated THEANO_FLAGS to work with 1.0.1
# (20180224) JP: changed the default bash mode to append
# (20180116) CC: modified the f command to query ldap server with getent
# (20171223) CC: added anaconda3 to the PATH
# (20171203) CC: removed -flto from $CFLAGS
# (20171029) CC: changed the formatting for the anaconda2 entry in the PATH
# (20171016) CC: updated PATH and LD_LIBRARY_PATH for torch
# (20170907) CC: edited qmn to grep for the default queue 
# (20170702) JP: added a env variable for the archiver
# (20170201) JP: deleted the www directory dependenc
# (20161104) PS: add variables for perl/f4de
# (20161024) JP: added a new alias, qmn
# (20161004) JP: cosmetic: changed an error message
# (20161004) PS: removed all exit -1 commands
# (20160928) PS: defined KERAS_BACKEND for keras
# (20160924) JP: changed the definition of the f alias
# (20160910) JP: cleaned up some edits with bash and other things
# (20160712) JP: simplified the mess made with CFLAGS
# (20160711) JP: cleaned up the mess made with CFLAGS
# (20160710) PS: make htk compliant with organization.
# (20160710) PS: add flags to optimize compiled code
# (20160706) PS: add all kaldi and kaldi-dep to path.
# (20160705) PS: add libresample to ld_library_path.
# (20160628) PS: add rcs bin path.
# (20160626) PS: add gperf bin path.
# (20160626) PS: add hwloc lib and bin paths.
# (20160626) PS: add nvml lib path.
# (20160625) PS: add cuda bin and lib paths.
# (20160622) PS: removed cxxflags and cflags. updated theano flags.
# (20160622) PS: removed march additions, updated bin and lib paths.
# (20160618) JP: cleaned up the march additions
# (20160617) PS: reduce CPATH and LIBRARY_PATH to the minimum for theano
# (20160517) PS: updated KALDI_ROOT for multiarch hooks
# (20160514) PS: adding paths for recompiled software with renamed dirs
# (20160513) PS: replaced invalid gcc variables. added flags for openmp.
# (20160511) PS: set C/CXX flags to gcc term for march, set theano flags
# (2016050X) PS: update PATH's while cleaning /common
# (20160429) JP: added hooks for the microarchitecture
# (20130626) JP: updated for OwlsNest
# (20130621) JP: reverted config.guess to "uname -i"
#

# define some important constants
#
PROGRAM_NAME="shell_bashrc.sh";

DEFAULT_ISIP_DATA="$DEFAULT_ISIP/data";
DEFAULT_ISIP_EXP="$DEFAULT_ISIP/exp";
DEFAULT_ISIP_WWW="$DEFAULT_ISIP/www";

DEFAULT_ISIP_UMASK="002";
DEFAULT_ISIP_HISTSIZE="9999";

DEFAULT_ISIP_TERM="vt100";
DEFAULT_ISIP_EDITOR="emacs";
DEFAULT_ISIP_EDITOR_INIT_FILE="$HOME/login/editor_emacs_init.el";

#------------------------------------------------------------------------------
# general isip stuff goes here:
#  this section usually sets the path, defines environment variables, etc.
#------------------------------------------------------------------------------

# define the location of the isip environment
#
ISIP=${ISIP:-"$DEFAULT_ISIP"};
if (test ! -d "$ISIP"); then
    echo "<$PROGRAM_NAME>:" "\$ISIP = $ISIP:"
    echo "\tthe isip environment is not properly set up -1-!";
fi

# define the location of isip data
#
ISIP_DATA=${ISIP_DATA:-"$DEFAULT_ISIP_DATA"};
if (test ! -d "$ISIP_DATA"); then
    echo "<$PROGRAM_NAME>:" "\$ISIP_DATA = $ISIP_DATA:"
    echo -e "\tthe isip environment is not properly set up -2-!";
fi

# define the location of isip exp
#
ISIP_EXP=${ISIP_EXP:-"$DEFAULT_ISIP_EXP"};
if (test ! -d "$ISIP_EXP"); then
    echo "<$PROGRAM_NAME>:" "\$ISIP_EXP = $ISIP_EXP:"
    echo -e "\tthe isip environment is not properly set up -3-!";
fi

# define the location of the isip tools
#
ISIP_TOOLS=${ISIP_TOOLS:-"$DEFAULT_ISIP_TOOLS"};
if (test ! -d "$ISIP_TOOLS"); then
    echo "<$PROGRAM_NAME>:" "\$ISIP_TOOLS = $ISIP_TOOLS:"
    echo -e "\tthe isip environment is not properly set up -4-!";
fi

# define the location of the isip www
#
ISIP_WWW=${ISIP_WWW:-"$DEFAULT_ISIP_WWW"};
if (test ! -d "$ISIP_WWW"); then
    echo "<$PROGRAM_NAME>:" "\$ISIP_WWW = $ISIP_WWW:"
    echo -e "\tthe isip environment is not properly set up -5-!";
fi

# export the important environment variables
#
isip="$ISIP";
isip_data="$ISIP_DATA";
isip_exp="$ISIP_EXP";
isip_tools="$ISIP_TOOLS";
isip_www="$ISIP_WWW";

export ISIP ISIP_DATA ISIP_EXP ISIP_TOOLS ISIP_WWW;
export isip isip_data isip_exp isip_tools isip_www;

#------------------------------------------------------------------------------
# general nedc stuff goes here
#------------------------------------------------------------------------------

# define the nedc environment variables
#
NEDC="/data/nedc";
nedc="$NEDC";
NEDC_NFC="$ISIP_TOOLS/nfc";
nedc_nfc="$NEDC_NFC";

# export the nedc environment variables
#
export NEDC NEDC_NFC;
export nedc nedc_nfc;

#------------------------------------------------------------------------------
# start building the environment
#------------------------------------------------------------------------------

# initialize the path starting with the current directory
#
PATH=".";

# add tools/common extensions:
#  these are tools that should precede the OS-related stuff
#
PATH="$PATH:$ISIP_TOOLS/common/asap/current/bin"
PATH="$PATH:$ISIP_TOOLS/common/aspell/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/binutils/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/cuda/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/emacs/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/gcc/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/imagemagick/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/matlab/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/sox/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/valgrind/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/rcs/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/qupath/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/sass/current/bin";
PATH="$PATH:$ISIP_TOOLS/common/lightgbm/current"

# add the system-level directories and site-specific packages
#
PATH="$PATH:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/bin";

# add nedc stuff to the path
#
PATH="$PATH:$NEDC_NFC/bin";

# export the path
#
export PATH;

# export the python path
#
PYTHONPATH="$NEDC_NFC/lib:.";
export PYTHONPATH;

# set and export LD_LIBRARY_PATH
#   only add to the path if necessary, prefer ISIP_LIBS when possible
#
LD_LIBRARY_PATH="$ISIP_TOOLS/common/gcc/current/lib"
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$ISIP_TOOLS/common/gcc/current/lib64";
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$ISIP_TOOLS/common/binutils/current/lib";
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$ISIP_TOOLS/common/boost/current/lib";
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$ISIP_TOOLS/common/cuda/current/lib64";
#LD_LIBRARY_PATH="$LD_LIBRARY_PATH:-I$ISIP_TOOLS/common/eigen/current";
export LD_LIBRARY_PATH;

# sets C++ path
#
CPLUS_INCLUDE_PATH="$ISIP_TOOLS/common/eigen/current/include/eigen3:$CPLUS_INCLUDE_PATH"
export CPLUS_INCLUDE_PATH

# When GPUs are requested via Slurm, CUDA_VISIBLE_DEVICES will be set to
# the list of available GPUs and we do not want to modify it.
# However, when no GPUs are requested, Slurm won't touch CUDA_VISIBLE_DEVICES,
# so it will be unset. Therefore, we want to set it to an empty string if it
# is unset, to require cluster users to request GPUs to use them.
#
if [ -z ${CUDA_VISIBLE_DEVICES+x} ]; then
    export CUDA_VISIBLE_DEVICES=''
fi

# define the isip libraries
#
OPS_LIB=$ISIP_TOOLS/common/openslide/current/lib

ISIP_LIBS="-L$NEDC_NFC/lib -ldsp \
	   -L$ISIP_TOOLS/common/anaconda3/current/envs/nedc/lib/ \
           -L$ISIP_TOOLS/common/boost/current/lib/ -lboost_program_options \
           -L$OPS_LIB -Wl,-rpath,$OPS_LIB -lopenslide -ldicom \
	   -lm"
export ISIP_LIBS;

# define the location of /tmp
#
ISIP_TMPDIR="/tmp";
export ISIP_TMPDIR;

# define compiler related things:
#  (0) the make file tool and priority
#  (1) the location of include files
#  (2) the C++ compiler
#  (3) the C++ optimize option
#  (4) abstracted the ar command due to GPU issues
#
ISIP_MAKE="nice -5 make";
ISIP_CPLUS_COMPILER="g++";
ISIP_CPLUS_OPTIMIZE="-O2";
ISIP_ARCHIVE_COMMAND="gcc-ar";

ISIP_INCLUDE="-I$NEDC_NFC/include \
              -I/opt/homebrew/include \
              -I$ISIP_TOOLS/common/boost/current/include";

export ISIP_MAKE ISIP_INCLUDE;
export ISIP_CPLUS_COMPILER ISIP_CPLUS_OPTIMIZE ISIP_ARCHIVE_COMMAND;

# define some global error codes to be used for shellscripts
#
ISIP_NOERROR="0";
ISIP_ERROR="1";

#------------------------------------------------------------------------------
# general user-level stuff goes here:
#  this section usually defines things that affect the user's interactive
#  environment.
#------------------------------------------------------------------------------

# set LOGNAME: since this is expensive, we only want to do it once
#
# define a username variable:
#  doing this in a standard way is becoming increasingly difficult
#
ISIP_USERNAME=`/usr/bin/id | cut -f2 -d'(' | cut -f1 -d')'`;
LOGNAME="$ISIP_USERNAME";
export ISIP_USERNAME LOGNAME;

# set default protection
#
umask $DEFAULT_ISIP_UMASK;

# set core file size to something small (realistic)
#
ulimit -c 0;

# set append mode
#
shopt -s histappend;

# suppress the shell warning message
#
export BASH_SILENCE_DEPRECATION_WARNING=1;

# turn off ctrl-d
#
export IGNOREEOF=1;

# set history length
#
HISTSIZE=$DEFAULT_ISIP_HISTSIZE;

# prevent storing adjacent identical lines in the bash history
#
history_control="ignoredups";

# set and export ISIP_HOST for the shell prompt
#
ISIP_HOST=`uname -n | cut -d. -f1`;
export ISIP_SERVER ISIP_HOST;

# set the editor
#
unset EDITOR;
EDITOR=${EDITOR:-"$DEFAULT_ISIP_EDITOR"};
ISIP_EDITOR_INIT_FILE=$DEFAULT_ISIP_EDITOR_INIT_FILE;
export EDITOR ISIP_EDITOR_INIT_FILE;

#------------------------------------------------------------------------------
# anaconda environment setup goes here:
#  the commands below are to be executed to setup the user's bash shell
#  to support the anaconda environment commands. there are three steps:
#
#  (1) activate the correct environment
#  (2) check the integrity of the environment
#  (3) unset the conda set up environment variable
#  (4) explicitly activate the nedc environment
#  (5) explicitly set qt plugin path for pyqt6 in nedc environment
#------------------------------------------------------------------------------

# (1) activate the correct environment:
#
#     - the user's condarc is edited to make sure (base) does not appear
#       in the user's bash session.
#
#     - turn off auto_activate_base (which tells conda not to activate
#       the base environment on startup). we do this since we use the
#       `nedc` environment as our base, and the `base` environment only
#       for administering conda.
#
$ISIP_TOOLS/common/anaconda3/current/bin/conda config --set changeps1 false
$ISIP_TOOLS/common/anaconda3/current/bin/conda config \
    --set auto_activate_base false
__conda_setup="$('$ISIP_TOOLS/common/anaconda3/current/bin/conda'" \
   "'shell.bash' 'hook' 2> /dev/null)"

# (2) check the integrity of the environment:
#     checks if the _conda_setup was ran successfully or not and
#     then cleans up the env
#
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    # calls the conda.sh script which sets up the conda activate and deactivate
    # commands. it also handles the new python path whenever an environment
    # is activated.
    #
    if [ -f "$ISIP_TOOLS/common/anaconda3/current/etc/profile.d/conda.sh" ];
    then
        . "$ISIP_TOOLS/common/anaconda3/current/etc/profile.d/conda.sh"
    fi
fi

# (3) check the integrity of the environment:
#     unsets the variable as it is no longer needed
# 
unset __conda_setup

# (4) explicitly activate the nedc environment, which contains the nedc
#     conda packages
#
conda activate nedc_03.11

# (5) explicitly set qt platform plugin path for pyqt6 in nedc_03.11
#     not that the environment variable CONDA_PREFIX is set in step (4).
#
export QT_QPA_PLATFORM_PLUGIN_PATH=$CONDA_PREFIX/lib/qt6/plugins/platforms

#------------------------------------------------------------------------------
#  interactive stuff goes here:
#  the commands below are to be executed for interactive shells only.
#  to determine if the shell is interactive, test for PS1.
#------------------------------------------------------------------------------
if (test -n "$PS1") then

    # Check window size, assure proper command line text wrapping.
    #
    shopt -s checkwinsize;
   
    # Expand directory names upon tab at command line. This is standard
    # behavior on macs
    #
    if (test `uname` != "Darwin") then
        shopt -s direxpand;
    fi
      
    # Append to history file rather than overwrite with last read copy.
    #
    shopt -s histappend;

    # update prompt
    #
    PS1=$ISIP_HOST"_[$SHLVL]: ";
    PS2=$ISIP_HOST"_[$SHLVL]? ";
    export PS1 PS2;

    # set some useful stuff for non-X terminal logins - a non-X
    # term has no DISPLAY set automatically.
    #
    if (test -z "$DISPLAY") then

        # set terminal type to the lowest common denominator - a vt100
        # (crude, but reliable)
        #
        TERM=${TERM:-"$DEFAULT_ISIP_TERM"};
        export TERM;

        # set USER, which for some reason does not always get set
        #
        USER="$ISIP_USERNAME";
        export USER;
    fi

    #--------------------------------------------------------------------------
    # define some extremely useful commands:
    #
    # the commands defined here should satisfy two requirements -
    #  (1) no standard unix alias exist for these commands
    #  (2) the command name length is limited to two characters
    #
    # all other commands in the isip environment are prefaced with "isip_".
    # since some of the commands defined below are frequently used, they
    # are allowed to exist without a standard prefix. the downside of this
    # is that they might cause a conflict with commands from another
    # environment (for example, several years ago, the show file command
    # "sf" was eliminated because it caused conflicts with some third
    # party environments.
    #--------------------------------------------------------------------------

    # define directory commands:
    #  due to the nature of shell programming, these must be defined using
    #  functions, so that they can be part of the user level environment
    #  these must also be in the bashrc so that they are available for
    #  any shell.
    #
    p  () { echo $PWD; }
    sd () { pushd $1 > /dev/null; echo $PWD; }
    td () { pushd    > /dev/null; echo $PWD; }
    pd () { popd  $1 > /dev/null; echo $PWD; }
    fd () { pushd $1 > /dev/null; echo $PWD":"; ls -1; }
    m  () { more $*; }

    # define a shell function for the find user alias:
    #  we need to do this outside of the case statement below
    #  to avoid some problems we encountered with certain environments
    #
    find_user () { for arg in `dscl . -list /Users | grep -i $1`; do
		       dscacheutil -q user -a name $arg; done }

    # define useful aliases
    #  we need to do this for some tools that have version numbers
    #
    alias cmake='cmake3'

    # define useful short unix commands:
    #  these are designed to include the most common and useful featrues
    #  of standard unix commands. note that the color option on the ls (d)
    #  command is Linux specific. on a mac, "-G" turns on color. getent is not
    #  available on the mac OS.
    #
    #  also, we had to implement the shell functions as aliases to offset
    #  some problems we were seeing with other tools.
    #
    case `uname` in

        "Linux")
	    alias d='ls --color=none -cblFa'
	    alias f='getent passwd | grep -i'
            ;;

        "Darwin")
	    alias d='ls -cblFa'
	    alias f='find_user'
            ;;

    esac

    # make sure the tty settings are reasonable
    #  in Solaris 2.4, and various versions of X, this is required
    #  to make backspace and delete work properly. the options selected
    #  here were the result of much experimentation. we used to use stty sane,
    #  but that forces a 7-bit stream, which breaks some modem/tty connections.
    #
    stty erase \^? intr \^c echoe;

    # end of interactive shell
fi

#
# end of file
