workflow_sketch.sh 15.8 KB
Newer Older
1 2 3 4 5 6 7 8 9
#!/bin/bash

##############################
# Configurations             #
##############################
# Put aliBuild in the PATH env var
export PATH="/mnt/SSD/schnorr/python/bin:$PATH"
# Directory where runAnalysis.C is placed
export ALIROOT_SCRIPT_DIR=$(pwd)/aliRoot/
10
# Directory where Blender scripts are
11 12
export BLENDER_SCRIPT_DIR=$(pwd)/animate/
# alienv working directory
13 14
export ALIENV_WORK_DIR=/home/breno/alice/sw
export ALIENV_OS_SPEC=ubuntu1804_x86-64
15
export ALIENV_ID=AliPhysics/latest-aliroot5-user
16
# Put Blender 2.79b in the PATH env var
17 18 19
export PATH="/home/schnorr/install/blender-2.79-linux-glibc219-x86_64/:$PATH"

##############################
20
# Command-line options       #
21
##############################
22 23 24 25 26 27 28 29 30 31 32 33 34 35
# See the following link to understand the code below
# https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash

# saner programming env: these switches turn some bugs into errors
set -o errexit -o pipefail -o noclobber -o nounset

# -allow a command to fail with !’s side effect on errexit
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
! getopt --test > /dev/null
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
    echo 'I’m sorry, `getopt --test` failed in this environment.'
    exit 1
fi

36
OPTIONS=c:hdau:m:n:t:r:
37
LONGOPTS=camera:,mosaic,resolution:,fps:,transparency:,duration:,maxparticles:,minparticles:,numberofevents:,minavgpz:,minavgpt:,help,download,sample,url:,its,tpc,trd,emcal,blendersave,picpct:
38 39 40 41 42 43 44 45 46 47 48 49 50 51

# -regarding ! and PIPESTATUS see above
# -temporarily store output to be able to check for errors
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
# -pass arguments only via   -- "$@"   to separate them correctly
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
    # e.g. return value is 1
    #  then getopt has complained about wrong arguments to stdout
    exit 2
fi
# read getopt’s output this way to handle the quoting right:
eval set -- "$PARSED"

52 53 54
##############################
# Parse Parameters           #
##############################
55
CAMERA=Overview
56
MOSAIC=false
57 58
DURATION=10
RESOLUTION=100
59
FPS=24
60
TRANSPARENCY=1
61 62 63
MAX_PARTICLES=1000
MIN_PARTICLES=0
N_OF_EVENTS=10
64
MIN_AVG_PZ=0
65
MIN_AVG_PT=0
66 67
HELP=false
DOWNLOAD=false
68
SAMPLE=false
69
URL=
70 71 72 73
ITS=1 # 1 means "build this detector", while 0 means "don't"
TPC=1
TRD=1
EMCAL=1
74
BLENDERSAVE=0
75
PICPCT=80
76 77 78
# now enjoy the options in order and nicely split until we see --
while true; do
    case "$1" in
79 80 81 82 83
      -h|--help)
          HELP=true
          shift
          break
          ;;
84
      -d|--download)
85 86 87
          DOWNLOAD=true
          shift
          ;;
88
      -a|--sample)
89 90 91
          SAMPLE=true
          shift
          ;;
92 93
      -u|--url)
          URL="$2"
94 95
            shift 2
            ;;
96 97 98 99
      -m|--maxparticles)
          MAX_PARTICLES="$2"
          shift 2
          ;;
100 101 102 103 104 105 106 107
      --minparticles)
          MIN_PARTICLES="$2"
          shift 2
          ;;
      -n|--numberofevents)
          N_OF_EVENTS="$2"
          shift 2
          ;;
108 109 110 111
      --minavgpz)
          MIN_AVG_PZ="$2"
          shift 2
          ;;
112 113 114 115
      --minavgpt)
          MIN_AVG_PT="$2"
          shift 2
          ;;
116 117 118 119 120 121 122 123
      -t|--duration)
          DURATION="$2"
          shift 2
          ;;
      -r|--resolution)
          RESOLUTION="$2"
          shift 2
          ;;
124 125 126 127
      --fps)
          FPS="$2"
          shift 2
          ;;
128 129
      --transparency)
          TRANSPARENCY="$2"
130 131
          shift 2
          ;;
132
      -c|--camera)
133 134 135
      	  CAMERA="$2"
      	  shift 2
      	  ;;
136 137 138 139
      --mosaic)
          MOSAIC=true
          shift
          ;;
140 141 142 143
      --picpct)
      	  PICPCT="$2"
      	  shift 2
      	  ;;
144
      --its)
145 146 147
          ITS=0
          shift
          ;;
148
      --tpc)
149 150 151
          TPC=0
          shift
          ;;
152
      --trd)
153 154 155
          TRD=0
          shift
          ;;
156
      --emcal)
157 158 159
          EMCAL=0
          shift
          ;;
160 161 162 163
      --blendersave)
          BLENDERSAVE=1
          shift
          ;;
164 165 166 167 168
        --)
            shift
            break
            ;;
        *)
169
            echo "Programming error $*"
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
            exit 3
            ;;
    esac
done

##############################
# Usage                      #
##############################
function usage()
{
    # Using a here doc with standard out.
    cat <<-END
Usage:
------
   -h | --help
     Display this help
   -d | --download
     Download the AliESDs.root file using the provided URL
   -u | --url URL
     Provide the URL to uniquely identify a AliESDs.root dataset.
     This should be in the format provided by http://opendata.cern.ch.
     See example below.
192
   -m | --maxparticles VALUE
193 194
     Get only events for which its number of particles does not
     exceed VALUE.
195
   --minparticles VALUE
196 197
     Get only events for which its number of particles is greater than
     or equal to VALUE.
198 199
   -n | --numberofevents VALUE
     Set number of events to be animated inside chosen ESD file.
200 201 202 203
   --minavgpz VALUE
     Get only events for which its absolute value of average momentum in
     the z direction is greater than or equal to VALUE. Useful for animating
     events with 'boosts' of particles to the same side.
204 205 206 207
   --minavgpt VALUE
     Get only events for which its average transversal momentum is
     greater than or equal to VALUE. Useful for animating events with
     'boosts' of particles on the xy plane.
208 209 210 211
   -t | --duration VALUE
     Set the animation duration in seconds.
   -r | --resolution VALUE
     Set the animation resolution percentage.
212 213
   --fps VALUE
     Set number of frames per second in animation.
214 215 216
   --transparency VALUE
     Set detector transparency as a number greater than zero,
     where zero is full transparency and 1 is standard transparency
217 218 219
   -c | --camera VALUE
     Which camera to use for the animation, where VALUE
     is a comma-separated list (without spaces)
220
     Options: Barrel,Forward,Overview,AntiOverview (defaults to Overview)
221 222 223 224
   --mosaic
     Make animations in all four available cameras and combine them into
     a single 2x2 clip containing all perspectives, totalizing five generated
     .mp4 videos.
225 226
   --picpct VALUE
     Percentage of animation to take HD picture, saved along with the clip.
227
   -a | --sample
228 229
     Creates a sample Blender animation of Event 2 from URL
     http://opendata.cern.ch/record/1102/files/assets/alice/2010/LHC10h/000139038/ESD/0001/AliESDs.root
230
   --its
231
     Removes ITS detector from animation
232
   --tpc
233
     Removes TPC detector from animation
234
   --trd
235
     Removes TRD detector from animation
236
   --emcal
237
     Removes EMCal detector from animation
238 239
   --blendersave
     Saves Blender file along with animation clip
240 241 242 243 244 245 246

Example:
--------
$0 --url http://opendata.cern.ch/record/1103/files/assets/alice/2010/LHC10h/000139173/ESD/0004/AliESDs.root --download

END
}
247

248 249 250 251 252
# Fix CAMERA to be accepted by the for loop
if [[ $CAMERA != "" ]]; then
    CAMERA=$(echo $CAMERA | sed -e 's#,#Camera #g' -e 's#$#Camera#')
fi

253 254 255 256
if [[ $MOSAIC == "true" ]]; then
    CAMERA=$(echo "OverviewCamera BarrelCamera AntiOverviewCamera ForwardCamera")
fi

257 258 259 260 261 262 263
if [[ $HELP = "true" ]]; then
    usage
    exit
else
    echo "-------- Parsed parameters --------"
    echo "URL: $URL"
    echo "Download: $DOWNLOAD"
264
    echo "Sample: $SAMPLE"
265
    echo "Transparency Parameter: $TRANSPARENCY"
266 267
    echo "Duration: $DURATION"
    echo "Resolution: $RESOLUTION"
268
    echo "FPS: $FPS"
269
    echo "Max particles: ${MAX_PARTICLES}"
270 271
    echo "Min particles: ${MIN_PARTICLES}"
    echo "Number of events: ${N_OF_EVENTS}"
272
    echo "Min Average Z Momentum: ${MIN_AVG_PZ}"
273
    echo "Min Average Transversal Momentum: ${MIN_AVG_PT}"
274
    echo "Camera: $CAMERA"
275
    echo "Mosaic: $MOSAIC"
276
    echo "Picture Percentage: ${PICPCT}%"
277
    echo "-----------------------------------"
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
    echo "------------ Detectors ------------"
    if [[ $ITS = 1 ]]; then
      echo "Building ITS"
    fi
    if [[ $TPC = 1 ]]; then
      echo "Building TPC"
    fi
    if [[ $TRD = 1 ]]; then
      echo "Building TRD"
    fi
    if [[ $EMCAL = 1 ]]; then
      echo "Building EMCAL"
    fi
    if [[ $TPC = 0 && $TPC = 0 && $TRD = 0 && $EMCAL = 0 ]]; then
      echo "Not building any detectors"
    fi
    echo "-----------------------------------"

296 297
fi

298 299 300 301 302 303 304
# handle non-option arguments
if [[ $# -ne 0 ]]; then
    echo "$0: non-option arguments ($#, $*) are ignored."
    echo "Remove them manually as indicated between parenthesis."
    exit
fi

305 306 307 308
##############################
# Download Dataset           #
##############################
if [ "$DOWNLOAD" = "true" ]; then
309
    if [ -z $URL ]; then
310
        echo "Error. Must pass the dataset URL in order to download ESD file."
311 312 313
        usage
        exit
    fi
314 315 316
    echo "Downloading data."
    wget $URL

317 318 319 320 321 322 323 324 325 326 327 328
    ######################################
    # Established Unique ID based on URL #
    ######################################
    UNIQUEID=$(echo $URL | sed \
                         -e "s#http://opendata.cern.ch/##" \
                         -e "s#/AliESDs.root##" \
                         -e "s#files/assets/##" \
                         -e "s#/#_#g")

    echo "The unique ID is $UNIQUEID."

fi
329

330
##############################
331
# Sample synthetic animation#
332
##############################
333
if [ "$SAMPLE" = "true" ]; then
334
    ##############################
335
    # Phase 1: Blender animate   #
336 337
    ##############################
    pushd ${BLENDER_SCRIPT_DIR}
338
    for type in $CAMERA; do
339
      echo "Preparing sample animation with $type in Blender"
340
      blender -noaudio --background -P animate_particles.py -- -radius=0.05 -duration=${DURATION} -camera=${type} -datafile="d-esd-detail.dat" -simulated_t=0.03 -fps=${FPS} -resolution=${RESOLUTION} -transparency=${TRANSPARENCY} -stamp_note="opendata.cern.ch_record_1102_alice_2010_LHC10h_000139038_ESD_0001_2" -its=${ITS} -tpc=${TPC} -trd=${TRD} -emcal=${EMCAL} -blendersave=${BLENDERSAVE} -picpct=5
341
    done
342
    popd
343
    BLENDER_OUTPUT=.
344
    mkdir --verbose -p ${BLENDER_OUTPUT}
345
    mv --verbose /tmp/alice_blender ${BLENDER_OUTPUT}
346 347
    echo "Done."

348 349 350
##############################
# Animation from file        #
##############################
351
elif [ "$SAMPLE" = "false" ]; then
352

353
  # Verify if AliESDs.root is here
354 355 356
  ALIESD_ROOT_FILE=$(pwd)/AliESDs.root
  if ! [[ -f "$ALIESD_ROOT_FILE" ]]
  then
Lucas Mello Schnorr's avatar
Lucas Mello Schnorr committed
357 358
      echo "AliESDs.root not found."
      exit
359 360
  fi

361 362 363
  ############################
  # Phase 1: aliroot extract #
  ############################
364
  eval $(alienv -w ${ALIENV_WORK_DIR} -a ${ALIENV_OS_SPEC} load ${ALIENV_ID})
365
  pushd ${ALIROOT_SCRIPT_DIR}
366
  # Remove existing symbolic link
367
  rm -f --verbose AliESDs.root
368 369 370
  # Create a symbolic link to the actual AliESDs.root
  ln --verbose -s ${ALIESD_ROOT_FILE} AliESDs.root
  # Run the extraction tool
371
  aliroot runAnalysis.C
372

373 374 375 376 377 378 379 380 381 382 383 384 385 386
  if [ "$DOWNLOAD" = "false" ]; then

    UNIQUEID=$(more uniqueid.txt)
    echo "The unique ID is $UNIQUEID."
    rm uniqueid.txt

  fi

  # Create directory where animations will be saved
  popd
  BLENDER_OUTPUT=$(pwd)/$UNIQUEID
  mkdir --verbose -p ${BLENDER_OUTPUT}
  pushd ${ALIROOT_SCRIPT_DIR} # push back to aliroot directory

387 388 389
  #################################################
  # Phase 1: iteration for every event identifier #
  #################################################
390

391 392 393
  # Event counter for animating no more events than the informed amount
  EVENT_COUNTER=0

394 395 396 397
  # Get all extracted files
  EXTRACTED_FILES=$(ls -1 esd_detail-event_*.dat | sort --version-sort)
  for FILE_WITH_DATA in $EXTRACTED_FILES; do
      EVENT_ID=$(echo $FILE_WITH_DATA | \
398 399
                 sed -e "s#esd_detail-event_##" \
                   -e "s#\.dat##")
400 401
      EVENT_UNIQUE_ID=${UNIQUEID}_${EVENT_ID}

402
      if ! [[ -s $FILE_WITH_DATA ]]; then
403
          echo "File $FILE_WITH_DATA has zero size. Ignore and continue."
404
	        rm $FILE_WITH_DATA
405
          continue
406
      fi
407

408 409 410
      ##############################
      # Phase 2: blender animate   #
      ##############################
411 412 413

      LOCAL_FILE_WITH_DATA=${EVENT_UNIQUE_ID}.dat
      cp ${ALIROOT_SCRIPT_DIR}/$FILE_WITH_DATA \
414 415
       ${BLENDER_SCRIPT_DIR}/${LOCAL_FILE_WITH_DATA}

416 417
      rm $FILE_WITH_DATA

418 419
      NUMBER_OF_PARTICLES=$(wc -l ${BLENDER_SCRIPT_DIR}/$LOCAL_FILE_WITH_DATA | \
                        awk '{ print $1 }')
420

421 422
      AVERAGE_PZ=$(awk 'BEGIN {pzsum=0;n=0} {pzsum+=$8;n++} END {print sqrt(pzsum*pzsum/n/n)}' ${BLENDER_SCRIPT_DIR}/${LOCAL_FILE_WITH_DATA})

423
      AVERAGE_PT=$(awk 'BEGIN {ptsum=0;n=0} {ptsum+=$9;n++} END {print ptsum/n}' ${BLENDER_SCRIPT_DIR}/${LOCAL_FILE_WITH_DATA})
424

425 426 427
      echo "File $LOCAL_FILE_WITH_DATA has $NUMBER_OF_PARTICLES particles."
      echo "Average Z momentum: $AVERAGE_PZ"
      echo "Average transversal momentum $AVERAGE_PT"
428

429 430 431
      if (( $(echo "$AVERAGE_PT >= $MIN_AVG_PT" |bc -l) )); then
        if (( $(echo "$AVERAGE_PZ >= $MIN_AVG_PZ" |bc -l) )); then
          if [[ $NUMBER_OF_PARTICLES -le $MAX_PARTICLES && $NUMBER_OF_PARTICLES -ge $MIN_PARTICLES && $EVENT_COUNTER -lt $N_OF_EVENTS ]]; then
432

433 434
            # Increment event counter
            EVENT_COUNTER=$EVENT_COUNTER+1
435

436
            echo "Processing ${EVENT_UNIQUE_ID} ($NUMBER_OF_PARTICLES tracks) in Blender"
437

438
            pushd ${BLENDER_SCRIPT_DIR}
439

440 441
            for type in $CAMERA; do
                  echo "Processing ${EVENT_UNIQUE_ID} with $type in Blender"
442

443
                  blender -noaudio --background -P animate_particles.py -- -radius=0.05 -duration=${DURATION} -camera=${type} -datafile="${LOCAL_FILE_WITH_DATA}" -n_event=${EVENT_ID} -simulated_t=0.03 -fps=${FPS} -resolution=${RESOLUTION} -transparency=${TRANSPARENCY} -stamp_note="${EVENT_UNIQUE_ID}" -its=${ITS} -tpc=${TPC} -trd=${TRD} -emcal=${EMCAL} -blendersave=${BLENDERSAVE} -picpct=${PICPCT}
444 445
                  echo "${type} for event ${EVENT_UNIQUE_ID} done."
            done
446

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
            if [ "$MOSAIC" = "true" ]; then

              popd
              pushd /tmp/alice_blender

              # Move animation images to final location
              mv /tmp/alice_blender/*.png ${BLENDER_OUTPUT}

              # Setting input names for clips in order to make mosaic clip
              INPUT_ONE=$(ls | awk 'NR==1')
              INPUT_TWO=$(ls | awk 'NR==2')
              INPUT_THREE=$(ls | awk 'NR==3')
              INPUT_FOUR=$(ls | awk 'NR==4')

              ffmpeg -i ${INPUT_FOUR} -i ${INPUT_TWO} -i ${INPUT_THREE} -i ${INPUT_ONE} -filter_complex "[0:v][1:v]hstack=inputs=2[top];[2:v][3:v]hstack=inputs=2[bottom];[top][bottom]vstack=inputs=2[v]" -map "[v]" ${EVENT_UNIQUE_ID}_Mosaic.mp4

              popd
              pushd ${BLENDER_SCRIPT_DIR}

            fi

            # Move generated clips to final location
            mv /tmp/alice_blender/* ${BLENDER_OUTPUT}

471 472
            # Move processed file to final location
            mv $LOCAL_FILE_WITH_DATA ${BLENDER_OUTPUT}/$LOCAL_FILE_WITH_DATA
473

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
            popd
            echo "EVENT ${EVENT_UNIQUE_ID} DONE with FILE $LOCAL_FILE_WITH_DATA."
          else

            if [[ $NUMBER_OF_PARTICLES -lt $MIN_PARTICLES ]]; then
              echo "Too little particles (minimum accepted is $MIN_PARTICLES). Continue."
            elif [[ $NUMBER_OF_PARTICLES -gt $MAX_PARTICLES ]]; then
              echo "Too many particles (maximum accepted is $MAX_PARTICLES). Continue."
            elif [[ $EVENT_COUNTER -ge $N_OF_EVENTS ]]; then
              echo "Numbers of events set to be animated has already been reached. Continue."
            fi

            # Remove non-processed files
            pushd ${BLENDER_SCRIPT_DIR}
            rm $LOCAL_FILE_WITH_DATA
            popd

            continue
492
          fi
493 494
        else
          echo "Average Z Momentum too low (minimum accepted is $MIN_AVG_PZ). Continue."
495

496 497 498 499 500 501
          # Remove non-processed files
          pushd ${BLENDER_SCRIPT_DIR}
          rm $LOCAL_FILE_WITH_DATA
          popd
        fi
      else
502
        echo "Average Transversal Momentum too low (minimum accepted is $MIN_AVG_PT). Continue."
503 504 505 506 507

        # Remove non-processed files
        pushd ${BLENDER_SCRIPT_DIR}
        rm $LOCAL_FILE_WITH_DATA
        popd
508
      fi
Lucas Mello Schnorr's avatar
Lucas Mello Schnorr committed
509
  done
510
  popd
511

512
fi