setup.sh 12.5 KB
Newer Older
1
2
#!/usr/bin/env bash

3
setup() {
4
5
6
    #
    # prepare local variables
    #
Marcel Rieger's avatar
Marcel Rieger committed
7

8
9
    local this_file="$( [ ! -z "$ZSH_VERSION" ] && echo "${(%):-%x}" || echo "${BASH_SOURCE[0]}" )"
    local this_dir="$( cd "$( dirname "$this_file" )" && pwd )"
10
    local orig="$PWD"
11
    local setup_name="${1:-default}"
Marcel Rieger's avatar
Marcel Rieger committed
12
13
    local setup_is_default="false"
    [ "$setup_name" = "default" ] && setup_is_default="true"
14
15
16
17
18
19
20
21


    #
    # global variables
    # (DHI = Di Higgs Inference)
    #

    export DHI_BASE="$this_dir"
22
    interactive_setup "$setup_name" || return "$?"
23
    export DHI_STORE_REPO="$DHI_BASE/data/store"
24
25
26
    export DHI_EXAMPLE_CARDS_GGF="$( echo /afs/cern.ch/user/m/mfackeld/public/datacards/dnn_score_max/*_dnn_node_HH_2B2VTo2L2Nu_GluGlu_NLO/datacard.txt | sed 's/ /,/g' )"
    export DHI_EXAMPLE_CARDS_VBF="$( echo /afs/cern.ch/user/m/mfackeld/public/datacards/dnn_score_max/*_dnn_node_HH_2B2VTo2L2Nu_VBF_NLO/datacard.txt | sed 's/ /,/g' )"
    export DHI_EXAMPLE_CARDS="$DHI_EXAMPLE_CARDS_GGF,$DHI_EXAMPLE_CARDS_VBF"
27
28
29
30
    export DHI_ORIG_PATH="$PATH"
    export DHI_ORIG_PYTHONPATH="$PYTHONPATH"
    export DHI_ORIG_PYTHON3PATH="$PYTHON3PATH"
    export DHI_ORIG_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
31
32
33
34
    export DHI_SLACK_TOKEN="${DHI_SLACK_TOKEN:-}"
    export DHI_SLACK_CHANNEL="${DHI_SLACK_CHANNEL:-}"
    export DHI_TELEGRAM_TOKEN="${DHI_TELEGRAM_TOKEN:-}"
    export DHI_TELEGRAM_CHAT="${DHI_TELEGRAM_CHAT:-}"
35

Marcel Rieger's avatar
Marcel Rieger committed
36
37
38
39
40
    # lang defaults
    [ -z "$LANGUAGE" ] && export LANGUAGE="en_US.UTF-8"
    [ -z "$LANG" ] && export LANG="en_US.UTF-8"
    [ -z "$LC_ALL" ] && export LC_ALL="en_US.UTF-8"

41
42

    #
43
    # helper functions
44
45
46
47
    #

    # pip install helper
    dhi_pip_install() {
48
        PYTHONUSERBASE="$DHI_SOFTWARE" pip install --user --no-cache-dir "$@"
49
50
51
    }
    [ ! -z "$BASH_VERSION" ] && export -f dhi_pip_install

52
53
54
55
56

    #
    # combine setup
    #

57
    local combine_version="2"
58
59
60
    local flag_file_combine="$DHI_SOFTWARE/.combine_good"
    [ "$DHI_REINSTALL_COMBINE" = "1" ] && rm -f "$flag_file_combine"
    if [ ! -f "$flag_file_combine" ]; then
61
62
63
64
65
66
        echo "installing combine into $DHI_SOFTWARE/HiggsAnalysis/CombinedLimit"
        mkdir -p "$DHI_SOFTWARE"

        (
            cd "$DHI_SOFTWARE"
            rm -rf HiggsAnalysis/CombinedLimit
67
            git clone --depth 1 https://github.com/cms-analysis/HiggsAnalysis-CombinedLimit.git HiggsAnalysis/CombinedLimit && \
68
            cd HiggsAnalysis/CombinedLimit && \
69
70
            git fetch --tags && \
            git checkout tags/v8.2.0 && \
71
72
73
74
            source env_standalone.sh "" && \
            make -j && \
            make
        ) || return "$?"
75

76
        date "+%s" > "$flag_file_combine"
77
        echo "version $combine_version" >> "$flag_file_combine"
78
    fi
79
    export DHI_SOFTWARE_FLAG_FILES="$flag_file_combine"
80

81
82
83
84
85
86
87
88
89
    # check the version in the combine flag file and show a warning when there was an update
    if [ "$( cat "$flag_file_combine" | grep -Po "version \K\d+.*" )" != "$combine_version" ]; then
        2>&1 echo ""
        2>&1 echo "WARNING: your local combine installation is not up to date, please consider updating it in a new shell with"
        2>&1 echo "         > DHI_REINSTALL_COMBINE=1 source setup.sh $( $setup_is_default || echo "$setup_name" )"
        2>&1 echo ""
    fi

    # source it
Marcel Rieger's avatar
Marcel Rieger committed
90
91
92
93
94
95
    cd "$DHI_SOFTWARE/HiggsAnalysis/CombinedLimit"
    source env_standalone.sh "" || return "$?"
    # the setup script appends to PATH, but we need to prepend since some htcondor nodes seem to
    # have an other "combine" executable that gets picked instead
    export PATH="$PWD/exe:$PWD/scripts:$PATH"
    cd "$orig"
96
97
98
99
100
101
102
103


    #
    # minimal local software stack
    #

    # source externals
    for pkg in \
Marcel Rieger's avatar
Marcel Rieger committed
104
            libjpeg-turbo/1.3.1-omkpbe2 \
105
            py2-pip/9.0.3 \
Marcel Rieger's avatar
Marcel Rieger committed
106
107
108
109
            py2-numpy/1.16.2-pafccj \
            py2-scipy/1.2.1-pafccj \
            py2-sympy/1.3-pafccj \
            py2-matplotlib/2.2.3 \
110
111
112
113
114
115
116
117
118
            py2-cycler/0.10.0-gnimlf \
            py2-uproot/2.6.19-gnimlf \
            py2-requests/2.20.0 \
            py2-urllib3/1.25.3 \
            py2-idna/2.8 \
            py2-chardet/3.0.4-gnimlf \
            py2-ipython/5.5.0-ogkkac \
            py2-backports/1.0 \
            ; do
119
        source "/cvmfs/cms.cern.ch/slc7_amd64_gcc700/external/$pkg/etc/profile.d/init.sh" "" || return "$?"
120
121
122
123
    done

    # update paths and flags
    local pyv="$( python -c "import sys; print('{0.major}.{0.minor}'.format(sys.version_info))" )"
124
125
    export PATH="$DHI_BASE/bin:$DHI_BASE/dhi/scripts:$DHI_BASE/modules/law/bin:$DHI_SOFTWARE/bin:$PATH"
    export PYTHONPATH="$DHI_BASE:$DHI_BASE/modules/law:$DHI_BASE/modules/plotlib:$DHI_SOFTWARE/lib/python${pyv}/site-packages:$DHI_SOFTWARE/lib64/python${pyv}/site-packages:$PYTHONPATH"
126
    export PYTHONWARNINGS="ignore"
127
    export PYTHONNOUSERSITE="1"
128
129
130
    export GLOBUS_THREAD_MODEL="none"
    ulimit -s unlimited

131
    # local stack
Marcel Rieger's avatar
Marcel Rieger committed
132
    local sw_version="1"
133
134
135
    local flag_file_sw="$DHI_SOFTWARE/.sw_good"
    [ "$DHI_REINSTALL_SOFTWARE" = "1" ] && rm -f "$flag_file_sw"
    if [ ! -f "$flag_file_sw" ]; then
136
        echo "installing software stack into $DHI_SOFTWARE"
Marcel Rieger's avatar
Marcel Rieger committed
137
        rm -rf "$DHI_SOFTWARE/lib"
138
139
140
        mkdir -p "$DHI_SOFTWARE"

        # python packages
Marcel Rieger's avatar
Marcel Rieger committed
141
142
        dhi_pip_install six==1.15.0 || return "$?"
        dhi_pip_install luigi==2.8.13 || return "$?"
143
        dhi_pip_install --no-deps git+https://github.com/riga/scinum.git || return "$?"
Peter Fackeldey's avatar
Peter Fackeldey committed
144
        dhi_pip_install tabulate==0.8.7 || return "$?"
145

146
147
148
        # optional packages, disabled at the moment
        # dhi_pip_install python-telegram-bot==12.3.0

149
        date "+%s" > "$flag_file_sw"
Marcel Rieger's avatar
Marcel Rieger committed
150
        echo "version $sw_version" >> "$flag_file_sw"
151
    fi
152
    export DHI_SOFTWARE_FLAG_FILES="$DHI_SOFTWARE_FLAG_FILES $flag_file_sw"
153

Marcel Rieger's avatar
Marcel Rieger committed
154
155
156
157
158
159
160
161
    # check the version in the sw flag file and show a warning when there was an update
    if [ "$( cat "$flag_file_sw" | grep -Po "version \K\d+.*" )" != "$sw_version" ]; then
        2>&1 echo ""
        2>&1 echo "WARNING: your local software stack is not up to date, please consider updating it in a new shell with"
        2>&1 echo "         > DHI_REINSTALL_SOFTWARE=1 source setup.sh $( $setup_is_default || echo "$setup_name" )"
        2>&1 echo ""
    fi

162
    # gfal2 bindings (optional)
Marcel Rieger's avatar
Marcel Rieger committed
163
164
165
    local lcg_dir="/cvmfs/grid.cern.ch/centos7-ui-4.0.3-1_umd4v3/usr"
    if [ ! -d "$lcg_dir" ]; then
        2>&1 echo "lcg directory $lcg_dir not existing, cannot setup gfal2 bindings"
166
167
168
169
    else
        export DHI_GFAL_DIR="$DHI_SOFTWARE/gfal2"
        export GFAL_PLUGIN_DIR="$DHI_GFAL_DIR/plugins"
        export PYTHONPATH="$DHI_GFAL_DIR:$PYTHONPATH"
Marcel Rieger's avatar
Marcel Rieger committed
170

171
172
173
174
        local flag_file_gfal="$DHI_SOFTWARE/.gfal_good"
        [ "$DHI_REINSTALL_GFAL" = "1" ] && rm -f "$flag_file_gfal"
        if [ ! -f "$flag_file_gfal" ]; then
            echo "linking gfal2 bindings"
Marcel Rieger's avatar
Marcel Rieger committed
175

176
177
            rm -rf "$DHI_GFAL_DIR"
            mkdir -p "$GFAL_PLUGIN_DIR"
178

179
180
            ln -s $lcg_dir/lib64/python2.7/site-packages/gfal2.so "$DHI_GFAL_DIR" || return "$?"
            ln -s $lcg_dir/lib64/gfal2-plugins/libgfal_plugin_* "$GFAL_PLUGIN_DIR" || return "$?"
Marcel Rieger's avatar
Marcel Rieger committed
181

182
183
184
            date "+%s" > "$flag_file_gfal"
        fi
        export DHI_SOFTWARE_FLAG_FILES="$DHI_SOFTWARE_FLAG_FILES $flag_file_gfal"
Marcel Rieger's avatar
Marcel Rieger committed
185
186
    fi

187

188
189
190
191
192
193
194
    #
    # initialze some submodules
    #

    if [ -d "$DHI_BASE/.git" ]; then
        for m in law plotlib; do
            local mpath="$DHI_BASE/modules/$m"
195
            # initialize the submodule when the directory is empty
196
            local mfiles=( "$mpath"/* )
197
            if [ "${#mfiles}" = "0" ]; then
198
                git submodule update --init --recursive "$mpath"
199
200
201
202
203
204
205
            else
                # update when not on a working branch and there are no changes
                local detached_head="$( ( cd "$mpath"; git symbolic-ref -q HEAD &> /dev/null ) && echo true || echo false )"
                local changed_files="$( cd "$mpath"; git status --porcelain=v1 2> /dev/null | wc -l )"
                if ! $detached_head && [ "$changed_files" = "0" ]; then
                    git submodule update --init --recursive "$mpath"
                fi
206
207
208
209
210
            fi
        done
    fi


211
212
213
214
215
216
217
218
    #
    # law setup
    #

    export LAW_HOME="$DHI_BASE/.law"
    export LAW_CONFIG_FILE="$DHI_BASE/law.cfg"

    # source law's bash completion scipt
219
    which law &> /dev/null && source "$( law completion )" ""
220
}
Marcel Rieger's avatar
Marcel Rieger committed
221
222

interactive_setup() {
223
    local setup_name="${1:-default}"
224
225
    local env_file="${2:-$DHI_BASE/.setups/$setup_name.sh}"
    local env_file_tmp="$env_file.tmp"
Marcel Rieger's avatar
Marcel Rieger committed
226

227
228
229
230
    # check if the setup is the default one
    local setup_is_default="false"
    [ "$setup_name" = "default" ] && setup_is_default="true"

Marcel Rieger's avatar
Marcel Rieger committed
231
232
    # when the setup already exists and it's not the default one,
    # source the corresponding env file and stop
233
234
235
236
237
238
239
240
    if ! $setup_is_default; then
        if [ -f "$env_file" ]; then
            echo -e "using variables for setup '\x1b[0;49;35m$setup_name\x1b[0m' from $env_file"
            source "$env_file" ""
            return "0"
        else
            echo -e "no setup file $env_file found for setup '\x1b[0;49;35m$setup_name\x1b[0m'"
        fi
Marcel Rieger's avatar
Marcel Rieger committed
241
242
    fi

243
244
245
246
247
248
249
250
    export_and_save() {
        local varname="$1"
        local value="$2"

        export $varname="$value"
        ! $setup_is_default && echo "export $varname=\"$value\"" >> "$env_file_tmp"
    }

Marcel Rieger's avatar
Marcel Rieger committed
251
252
253
254
255
    query() {
        local varname="$1"
        local text="$2"
        local default="$3"
        local default_text="${4:-$default}"
256
257
258
259
260
261

        # when the setup is the default one, use the default value when the env variable is empty,
        # otherwise, query interactively
        local value="$default"
        if $setup_is_default; then
            [ ! -z "${!varname}" ] && value="${!varname}"
Marcel Rieger's avatar
Marcel Rieger committed
262
        else
263
            printf "$text (\x1b[1;49;39m$varname\x1b[0m, default \x1b[1;49;39m$default_text\x1b[0m):  "
264
            read query_response
Marcel Rieger's avatar
Marcel Rieger committed
265
            [ "X$query_response" = "X" ] && query_response="$default"
266

Marcel Rieger's avatar
Marcel Rieger committed
267
268
269
270
            # repeat for boolean flags that were not entered correctly
            while true; do
                ( [ "$default" != "True" ] && [ "$default" != "False" ] ) && break
                ( [ "$query_response" = "True" ] || [ "$query_response" = "False" ] ) && break
271
                printf "please enter either '\x1b[1;49;39mTrue\x1b[0m' or '\x1b[1;49;39mFalse\x1b[0m':  " query_response
272
                read query_response
Marcel Rieger's avatar
Marcel Rieger committed
273
274
                [ "X$query_response" = "X" ] && query_response="$default"
            done
275

276
277
278
279
280
281
282
            # save the expanded value
            value="$( eval "echo $query_response" )"
            # strip " and '
            value=${value%\"}
            value=${value%\'}
            value=${value#\"}
            value=${value#\'}
Marcel Rieger's avatar
Marcel Rieger committed
283
        fi
284
285

        export_and_save "$varname" "$value"
Marcel Rieger's avatar
Marcel Rieger committed
286
287
    }

288
    # prepare the tmp env file
289
    if ! $setup_is_default; then
290
291
292
        rm -rf "$env_file_tmp"
        mkdir -p "$( dirname "$env_file_tmp" )"

293
        echo -e "Start querying variables for setup '\x1b[0;49;35m$setup_name\x1b[0m', press enter to accept default values\n"
294
    fi
Marcel Rieger's avatar
Marcel Rieger committed
295
296

    # start querying for variables
297
    query DHI_USER "CERN / WLCG username" "$( whoami )"
Marcel Rieger's avatar
Marcel Rieger committed
298
    query DHI_DATA "Local data directory" "$DHI_BASE/data" "./data"
299
    query DHI_STORE "Default local output store" "$DHI_DATA/store" "\$DHI_DATA/store"
300
    query DHI_STORE_BUNDLES "Output store for software bundles when submitting jobs" "$DHI_STORE" "\$DHI_STORE"
Marcel Rieger's avatar
Marcel Rieger committed
301
302
    query DHI_STORE_EOSUSER "Optional output store in EOS user directory" "/eos/user/${DHI_USER:0:1}/${DHI_USER}/dhi/store"
    query DHI_SOFTWARE "Directory for installing software" "$DHI_DATA/software" "\$DHI_DATA/software"
303
    query DHI_DATACARDS_RUN2 "Location of the datacards_run2 repository (optional)" "" "''"
Marcel Rieger's avatar
Marcel Rieger committed
304
    query DHI_JOB_DIR "Directory for storing job files" "$DHI_DATA/jobs" "\$DHI_DATA/jobs"
305
    query DHI_TASK_NAMESPACE "Namespace (i.e. the prefix) of law tasks" "" "''"
Marcel Rieger's avatar
Marcel Rieger committed
306
307
308
309
    query DHI_LOCAL_SCHEDULER "Use a local scheduler for law tasks" "True"
    if [ "$DHI_LOCAL_SCHEDULER" != "True" ]; then
        query DHI_SCHEDULER_HOST "Address of a central scheduler for law tasks" "hh:cmshhcombr2@hh-scheduler1.cern.ch"
        query DHI_SCHEDULER_PORT "Port of a central scheduler for law tasks" "80"
310
    else
311
        export_and_save DHI_SCHEDULER_HOST "hh:cmshhcombr2@hh-scheduler1.cern.ch"
312
        export_and_save DHI_SCHEDULER_PORT "80"
Marcel Rieger's avatar
Marcel Rieger committed
313
314
315
    fi

    # move the env file to the correct location for later use
316
    if ! $setup_is_default; then
Marcel Rieger's avatar
Marcel Rieger committed
317
        mv "$env_file_tmp" "$env_file"
318
        echo -e "\nsetup variables written to $env_file"
Marcel Rieger's avatar
Marcel Rieger committed
319
320
321
    fi
}

322
323
324
325
326
327
328
329
330
331
332
action() {
    if setup "$@"; then
        echo -e "\x1b[0;49;35mHH inference tools successfully setup\x1b[0m"
        return "0"
    else
        local code="$?"
        echo -e "\x1b[0;49;31msetup failed with code $code\x1b[0m"
        return "$code"
    fi
}
action "$@"