6#--------------------------------------------------------------------------------------
8# Utility script for zsh library functions.
10#--------------------------------------------------------------------------------------
15if [[ "$DEBUG" == "" ]]; then
16typeset -i DEBUG=0 # debug level
20export DEFAULT_OPTION=-- # default option
22export ULIB_DIR=${0:h} # ulib directory
24# Wild card for any valid detector identifier or run number; to be used as ${~ANY}.
26export ANY_ID="[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"
28export PI=3.1415926535897931
36export TIMESTAMP=\#splitline{}{\#splitline{%d-%m-%y}{\ \ %H:%M}}%F1970-01-01\ 00:00:00
38# Array of variable set / unset with set_variable / unset_variable (see below).
40typeset -A ULIB_VARIABLES
43# Array of variables with default values defined with set_variable: or set_variable+ (see below).
45typeset -A UDEF_VARIABLES
52 echo -e $RED`date` FATAL $* $RESET
55function error() { if (( $DEBUG >= 0 )); then echo -e $RED`date` ERROR $* $RESET; fi }
56function notice() { if (( $DEBUG >= 1 )); then echo -e `date` NOTICE $* ; fi }
57function status() { if (( $DEBUG >= 2 )); then echo -e `date` STATUS $* ; fi }
58function warning() { if (( $DEBUG >= 2 )); then echo -e `date` WARNING $* ; fi }
59function debug() { if (( $DEBUG >= 3 )); then echo -e `date` DEBUG $* ; fi }
63# Method to check for usage of script.
65# \param 1-N list of command line options
66# \return 0 for option -h; else 1
70 for variable in $*; do
71 if [[ "$variable" == "-h!" ]]; then
76 for variable in $*; do
77 if [[ "$variable" == "-h" || "$variable" == "-h!" ]]; then
87# Method to print usage of script and exit.
95 if (( $DEBUG >= 3 )); then
96 print_array UDEF_VARIABLES
104# Method to print environment variables.
114# The last parameter refers to the exit code.
119function check_exit_code()
121 if (( $argv[-1] )); then
131# check exit code alias
133alias CHECK_EXIT_CODE="check_exit_code \$0 \$* \$?"
139# \param 1 first value
140# \param 2 second value
142function test_equality
144 if [[ "$1" != "$2" ]]; then
153# Method to check if inside a conda env.
157 if [ -n "${CONDA_PREFIX+1}" ]; then
166# Method to check for CC Lyon.
168# \return 1 for CC Lyon; else 0
174 if [[ -n "${LOCALHOST}" && "${LOCALHOST:0:2}" = "cc" ]]; then
182# Method to check if the local host corresponds to one of the Nikhef computer clusters
184# \return 1 if local host corresponds to one of the Nikhef computer clusters; else false
186function is_CCNikhef()
190 if [[ -n "${LOCALHOST}" && "${LOCALHOST:0:4}" == "stbc" ]]; then
199# Method to define variable.
203function define_variable()
207 eval export $variable
212# Method to set variable.
213# Note that a value equal to $DEFAULT_OPTION will not modify the variable.
218function set_variable()
223 if [[ "$*" != "$DEFAULT_OPTION" ]]; then
224 eval export $variable=\"$\*\"
227 eval ULIB_VARIABLES\[$variable\]=\"\$${variable}\"
232# Method to set variable.
233# The second variable corresponds to a possible default value.
234# If this variable is defined, the first variable is set to its value
235# else to the given value(s).
241function set_variable:()
249 eval value=\"\${$optional:-"$*"}\"
251 set_variable $variable $value
253 UDEF_VARIABLES[$variable]="$optional -> $value"
258# Method to set variable.
259# The second variable corresponds to a possible default value.
260# If this variable is defined, the first variable is set to the given value(s)
261# else to an empty value.
267function set_variable+()
275 eval value=\"\${$optional+"$*"}\"
277 set_variable $variable $value
279 UDEF_VARIABLES[$variable]="$optional -> $value"
284# Method to locally set variable.
285# Note that a value equal to $DEFAULT_OPTION will not modify the variable.
290function set_local_variable()
295 if [[ "$*" != "$DEFAULT_OPTION" ]]; then
296 eval $variable=\"$\*\"
302# Method to unset variable.
306function unset_variable()
311 eval unset \"ULIB_VARIABLES\[$variable\]\"
316# Method to print variables.
318# \param 1-N list of variables
320function print_variable()
322 for variable in $*; do
323 eval value=\${$variable}
324 printf "%-20s = %s\n" ${variable} "${value}"
330# Method to print associative array.
334function print_array()
340 eval keys=\(\${\(@k\)$array}\)
343 if (( ${#key} > $len )); then
349 eval printf \"%-${len}s = %s\\n\" $key \"\$${array}\[$key\]\"
355# Method to check validity of variables.
357# \param 1-N list of variables
359function check_variable()
361 for variable in $*; do
362 eval value=$+${variable}
363 if (( ${value} == 0 )); then
364 fatal "Variable ${variable} not defined."
371# Method to set array.
381 eval $variable=\($\*\)
386# Method to expand array.
388# Tokens <first>-<last> in the array are exanded to <first> <first + 1> .. <last>
392function expand_array()
394 eval __BUFFER__=\(\$$1\[\*\]\)
398 for RANGE in $__BUFFER__[*]; do
399 for (( i = ${RANGE%%-*}; $i <= ${RANGE##*-}; i += 1 )); do
407# Method to count directory in ':' separated path list.
412function count_directory()
417 echo -n $key | tr ":" "\n" | grep "^${value}$" | wc -w
422# Method to remove directory from ':' separated path list.
427function remove_directory()
432 if [[ -n "$key" && -n "$value" ]]; then
433 export $1=`echo $key | tr ":" "\n" | grep -v "^${value}$" | tr "\n" ":" | sed 's/:\$//'`
439# Method to remove variable from ':' separated path list.
444function remove_variable()
449 if [[ -n "$key" && -n "$value" ]]; then
450 remove_directory $1 $value
456# Method to insert directory into ':' separated path list.
461function insert_directory()
465 if [[ -z "$key" ]]; then
467 elif (( `echo -n $key | tr ":" "\n" | grep "^${2}$" | wc -w` == 0 )); then
474# Method to check process path.
476# \param 1-N list of process names
478function check_process()
480 for process in $*; do
482 local bin=`which $process 2>& /dev/null`
483 debug "Check process ${process}=${bin}"
485 if [ -z "${bin}" ]; then
486 fatal "Process ${process} not found."
493# Method to check file access.
495# \param 1-N list of files
497function check_input_file()
499 if (( $# == 0 )); then
500 fatal "No input file."
503 for file in `echo $*`; do
505 debug "Check input file: ${file}"
507 if [[ ! -f ${file} ]]; then
508 fatal "File ${file} not found."
509 elif [[ ! -r ${file} ]]; then
510 fatal "File ${file} not readable."
517# Method to check file access.
519# \param 1-N list of files
521function check_output_file()
523 for file in `echo $*`; do
525 debug "Check output file: ${file}"
527 if [[ -f ${file} ]]; then
528 fatal "File ${file} already exists."
535# Method to reuse file.
536# Note that this method may require user interaction.
539# \return 1 when absent; else 0
547 if [[ ! -f $1 ]]; then
558function get_ip_address()
560 if [[ $(uname) == "Darwin" ]]; then
561 arp $(hostname) | cut -d '(' -f 2 | cut -d ')' -f 1
563 hostname --all-ip-addresses | cut --delimiter=' ' -f1
569# Get process identifier.
577 if (( $# == 1 )); then
580 if (( $# == 2 )); then
587# Method to get least significant digit.
594 printf "%f\n" `echo $1 | sed -n "s/[+-]\?\([0-9]*.\?[0-9]*\)[1-9]\([0]*.\?\)/\1A\2/p" | sed 's/[1-9]/0/g' | sed 's/A/1/'`
602 if [[ $(uname) == "Darwin" ]]; then
610# Method to start timer
612function timer_start()
614 let "TIMER = $(get_time)"
619# Method to stop timer
623 let "TIMER = $(get_time) - $TIMER"
628# Method to print timer
630function timer_print()
632 printf "Elapsed time %1.3f s.\n" $TIMER
637# Method to print lap time
641 printf "Elapsed time %1.3f s.\n" $(($(get_time) - $TIMER))
646# Method to convert associative array to list of equations
648# \param 1 associative array
650function make_equation()
656 eval array=\(\${\(kv\)${1}}\)
660 for key in ${(k)array}; do
661 echo -n "$key = ${array[${key}]}; "
669# Test if associative array has given key.
671# \param 1 associative array
673# \return 1 if present; else 0
684# Make communication with process.
687# - FD_O is the actual file descriptor for writing to actual process and
688# - FD_I is the actual file descriptor for reading from process.
690# \param 1 process name
691# \param 2-N optional argument(s)
699 ARGS="$*" # optional arguments
701 FIFO_O=/tmp/${PROCESS}_writing.$$ # named pipe for writing
702 FIFO_I=/tmp/${PROCESS}_reading.$$ # named pipe for reading
707 mkfifo $FIFO_O # create a new FIFO
708 mkfifo $FIFO_I # create a new FIFO
710 eval "exec {FD_O}<>$FIFO_O" # attach file descriptor to FIFO
711 eval "exec {FD_I}<>$FIFO_I" # attach file descriptor to FIFO
713 # launch process in background and cleanup afterwards
725# Remove communication with process.
727# \param 1 file descriptor for writing to process
731 if (( $# == 0 )); then
742# Write to attachted prcess.
750# Read from attachted prcess.
754 eval read $* <\& $FD_I
759# alias to kill all child processes at exit of parent process
761alias kill_child_processes_at_exit="trap 'kill_child_processes $$' EXIT"
765# recursively kill child processes for given parent identifier.
767# \param 1 parent identifier
769kill_child_processes()
773 for child in `ps --ppid $pid -ho "%p"`; do
774 kill_child_processes $child
777 if (( $pid != $$ )); then
778 kill -9 $pid >& /dev/null
783alias sftpget="$ULIB_DIR/sftpget.zsh"
784alias sftpput="$ULIB_DIR/sftpput.zsh"