workflow_sketch.sh 23.2 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
export PATH="/home/schnorr/install/blender-2.79-linux-glibc219-x86_64/:$PATH"

19 20 21
# Progress log file
export PROGRESS_LOG=$(pwd)/progress.log

22 23 24 25 26 27 28 29
if [[ -f $PROGRESS_LOG ]]; then
  if grep -q "JOB FINISHED" $PROGRESS_LOG; then
    rm $PROGRESS_LOG
  fi
fi

# Define a timestamp function
timestamp() {
30
  date +"%y-%m-%d, %T, $1"
31 32
}

33
##############################
34
# Command-line options       #
35
##############################
36 37 38 39 40 41 42 43 44 45 46 47 48 49
# 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

50
OPTIONS=c:hdau:m:n:t:r:
51
LONGOPTS=cameras:,mosaic,resolution:,fps:,transparency:,duration:,radius:,maxparticles:,\
52
minparticles:,numberofevents:,minavgpz:,minavgpt:,help,download,sample,url:,its,\
53
tpc,detailedtpc,trd,emcal,blendersave,picpct:,bgshade:
54 55 56 57 58 59 60 61 62 63 64 65 66 67

# -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"

68 69 70
##############################
# Parse Parameters           #
##############################
71
CAMERAS=Overview
72
MOSAIC=false
73
DURATION=10
74
RADIUS=1
75
RESOLUTION=100
76
FPS=24
77
TRANSPARENCY=1
78 79 80
MAX_PARTICLES=1000
MIN_PARTICLES=0
N_OF_EVENTS=10
81
MIN_AVG_PZ=0
82
MIN_AVG_PT=0
83 84
HELP=false
DOWNLOAD=false
85
SAMPLE=false
86
URL=
87 88
ITS=1 # 1 means "build this detector", while 0 means "don't"
TPC=1
89
DETAILED_TPC=0
90 91
TRD=1
EMCAL=1
92
BLENDERSAVE=0
93
PICPCT=80
94
BGSHADE=0
95 96 97
# now enjoy the options in order and nicely split until we see --
while true; do
    case "$1" in
98 99 100 101 102
      -h|--help)
          HELP=true
          shift
          break
          ;;
103
      -d|--download)
104 105 106
          DOWNLOAD=true
          shift
          ;;
107
      -a|--sample)
108 109 110
          SAMPLE=true
          shift
          ;;
111 112
      -u|--url)
          URL="$2"
113 114
            shift 2
            ;;
115 116 117 118
      -m|--maxparticles)
          MAX_PARTICLES="$2"
          shift 2
          ;;
119 120 121 122 123 124 125 126
      --minparticles)
          MIN_PARTICLES="$2"
          shift 2
          ;;
      -n|--numberofevents)
          N_OF_EVENTS="$2"
          shift 2
          ;;
127 128 129 130
      --minavgpz)
          MIN_AVG_PZ="$2"
          shift 2
          ;;
131 132 133 134
      --minavgpt)
          MIN_AVG_PT="$2"
          shift 2
          ;;
135 136 137 138
      -t|--duration)
          DURATION="$2"
          shift 2
          ;;
139 140 141 142 143
      -r|--radius)
          RADIUS="$2"
          shift 2
          ;;
      --resolution)
144 145 146
          RESOLUTION="$2"
          shift 2
          ;;
147 148 149 150
      --fps)
          FPS="$2"
          shift 2
          ;;
151 152
      --transparency)
          TRANSPARENCY="$2"
153 154
          shift 2
          ;;
155 156
      -c|--cameras)
      	  CAMERAS="$2"
157 158
      	  shift 2
      	  ;;
159 160 161 162
      --mosaic)
          MOSAIC=true
          shift
          ;;
163 164 165 166
      --picpct)
      	  PICPCT="$2"
      	  shift 2
      	  ;;
167 168 169 170
      --bgshade)
      	  BGSHADE="$2"
      	  shift 2
      	  ;;
171
      --its)
172 173 174
          ITS=0
          shift
          ;;
175
      --tpc)
176 177 178
          TPC=0
          shift
          ;;
179 180 181 182
      --detailedtpc)
          DETAILED_TPC=1
          shift
          ;;
183
      --trd)
184 185 186
          TRD=0
          shift
          ;;
187
      --emcal)
188 189 190
          EMCAL=0
          shift
          ;;
191 192 193 194
      --blendersave)
          BLENDERSAVE=1
          shift
          ;;
195 196 197 198 199
        --)
            shift
            break
            ;;
        *)
200
            echo "Programming error $*"
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
            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.
223
   -m | --maxparticles VALUE
224 225
     Get only events for which its number of particles does not
     exceed VALUE.
226
   --minparticles VALUE
227 228
     Get only events for which its number of particles is greater than
     or equal to VALUE.
229
   -n | --numberofevents VALUE
230
     Set number of events to be animated inside chosen ESD file (defaults to 10)
231 232
   --minavgpz VALUE
     Get only events for which its absolute value of average momentum in
233 234
     the z direction is greater than or equal to VALUE, in GeV/c. Useful
     for animating events with 'boosts' of particles to the same side.
235 236
   --minavgpt VALUE
     Get only events for which its average transversal momentum is
237 238
     greater than or equal to VALUE, in GeV/c. Useful for animating
     events with 'boosts' of particles on the xy plane.
239 240
   -t | --duration VALUE
     Set the animation duration in seconds.
241 242 243 244
   -r | --radius VALUE
     Scale default particle radius to a given VALUE, greater than zero.
     For example, VALUE=2 scales particle to twice its default size.
   --resolution VALUE
245 246
     Set the animation resolution percentage, where
     VALUE must be an integer from 1 to 100.
247 248
   --fps VALUE
     Set number of frames per second in animation.
249 250 251
   --transparency VALUE
     Set detector transparency as a number greater than zero,
     where zero is full transparency and 1 is standard transparency
252 253
   -c | --cameras VALUE
     Which cameras to use for the animation, where VALUE
254
     is a comma-separated list (without spaces)
255
     Options: Barrel,Side,Forward,Overview,Moving1,Moving2,Moving3,Moving4 (defaults to Overview)
256
   --mosaic
257 258 259
     Make animations in all four available steady cameras and combine them into
     a single 2x2 clip containing all perspectives, totalizing at least five
     generated .mp4 videos.
260
   --picpct VALUE
261 262
     Percentage of animation to take HD picture, saved along with the clip,
     where VALUE must be an integer
263 264 265
   --bgshade VALUE
     Set background shade of black to VALUE, where 0 is totally black
     and 1 is totally white
266
   -a | --sample
267
     Creates a sample Blender animation of Event 2 from URL
268 269
     http://opendata.cern.ch/record/1102/files/assets/alice/2010/LHC10h/000139\
038/ESD/0001/AliESDs.root
270
   --its
271
     Removes ITS detector from animation
272 273
   --detailedtpc
     Includes more detailed version of TPC in animation
274
   --tpc
275
     Removes TPC detector from animation
276
   --trd
277
     Removes TRD detector from animation
278
   --emcal
279
     Removes EMCal detector from animation
280 281
   --blendersave
     Saves Blender file along with animation clip
282 283 284

Example:
--------
285 286
$0 --url http://opendata.cern.ch/record/1103/files/assets/alice/2010/LHC10h/000\
139173/ESD/0004/AliESDs.root --download
287 288 289

END
}
290

291
# Fix CAMERA to be accepted by the for loop
292 293
if [[ $CAMERAS != "" ]]; then
    CAMERAS=$(echo $CAMERAS | sed -e 's#,#Camera #g' -e 's#$#Camera#')
294 295
fi

296
# Set cameras properly if MOSAIC is called
297
if [[ $MOSAIC = "true" ]]; then
298

299
    CAMERAS+=" OverviewCamera BarrelCamera SideCamera ForwardCamera"
300

301 302
fi

303 304 305 306 307 308 309
if [[ $HELP = "true" ]]; then
    usage
    exit
else
    echo "-------- Parsed parameters --------"
    echo "URL: $URL"
    echo "Download: $DOWNLOAD"
310
    echo "Sample: $SAMPLE"
311
    echo "Transparency Parameter: $TRANSPARENCY"
312
    echo "Duration: $DURATION"
313
    echo "Particle Radius Scale: $RADIUS"
314
    echo "Resolution: $RESOLUTION"
315
    echo "FPS: $FPS"
316
    echo "Max particles: ${MAX_PARTICLES}"
317 318
    echo "Min particles: ${MIN_PARTICLES}"
    echo "Number of events: ${N_OF_EVENTS}"
319
    echo "Min Average Z Momentum: ${MIN_AVG_PZ}"
320
    echo "Min Average Transversal Momentum: ${MIN_AVG_PT}"
321
    echo "Cameras: $CAMERAS"
322
    echo "Mosaic: $MOSAIC"
323
    echo "Picture Percentage: ${PICPCT}%"
324
    echo "Background Shade: ${BGSHADE}"
325
    echo "-----------------------------------"
326 327 328 329
    echo "------------ Detectors ------------"
    if [[ $ITS = 1 ]]; then
      echo "Building ITS"
    fi
330 331 332 333 334 335
    if [[ $DETAILED_TPC = 1 ]]; then
      echo "Building detailed TPC"
    else
      if [[ $TPC = 1 ]]; then
        echo "Building TPC"
      fi
336 337 338 339 340 341 342 343 344 345 346 347
    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 "-----------------------------------"

348 349
fi

350 351 352 353 354
# Get number of frames
FPS_DUR="$FPS $DURATION"
FPS_DUR=$(echo $FPS_DUR | awk '{print $1*$2}')


355 356 357 358 359 360 361
# 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

362

363 364 365 366
##############################
# Download Dataset           #
##############################
if [ "$DOWNLOAD" = "true" ]; then
367
    if [ -z $URL ]; then
368
        echo "Error. Must pass the dataset URL in order to download ESD file."
369 370 371
        usage
        exit
    fi
372

373
    if ! grep -q "ESD DOWNLOAD DONE" $PROGRESS_LOG; then
374 375
      echo "Downloading data."
      wget $URL
376
      timestamp "ESD DOWNLOAD DONE" >> $PROGRESS_LOG
377
    fi
378

379 380 381 382 383 384 385 386 387 388 389 390
    ######################################
    # 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
391

392
##############################
393
# Sample synthetic animation#
394
##############################
395
if [ "$SAMPLE" = "true" ]; then
396
    ##############################
397
    # Phase 1: Blender animate   #
398
    ##############################
399 400 401
    BLENDER_OUTPUT=$(pwd)/sample
    mkdir --verbose -p ${BLENDER_OUTPUT}

402
    pushd ${BLENDER_SCRIPT_DIR}
403 404
    echo "Preparing sample animation in Blender"

405
    blender -noaudio --background -P animate_particles.py -- -radius=${RADIUS} \
406
    -duration=${DURATION} -cameras="${CAMERAS}" -datafile="d-esd-detail.dat" -simulated_t=0.03\
407 408
    -fps=${FPS} -resolution=${RESOLUTION} -transparency=${TRANSPARENCY} \
    -stamp_note="opendata.cern.ch_record_1102_alice_2010_LHC10h_000139038_ESD_0001_2" -its=${ITS}\
409
    -tpc=${TPC} -trd=${TRD} -emcal=${EMCAL} -detailed_tpc=${DETAILED_TPC} \
410
    -blendersave=1 -bgshade=${BGSHADE} -tpc_blender_path=${BLENDER_SCRIPT_DIR} \
411
    -output_path="${BLENDER_OUTPUT}"
412

413 414 415
    popd
    echo "Done."

416 417 418
##############################
# Animation from file        #
##############################
419
elif [ "$SAMPLE" = "false" ]; then
420

421
  if ! grep -q "DATA_ANALYSIS, FINISHED" $PROGRESS_LOG; then
422 423 424 425 426 427 428 429 430 431 432 433

    # Verify if AliESDs.root is here
    ALIESD_ROOT_FILE=$(pwd)/AliESDs.root
    if ! [[ -f "$ALIESD_ROOT_FILE" ]]
    then
        echo "AliESDs.root not found."
        exit
    fi

    ############################
    # Phase 1: aliroot extract #
    ############################
434
    timestamp "STARTING DATA ANALYSIS" >> $PROGRESS_LOG
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
    eval $(alienv -w ${ALIENV_WORK_DIR} -a ${ALIENV_OS_SPEC} load ${ALIENV_ID})
    pushd ${ALIROOT_SCRIPT_DIR}
    # Remove existing symbolic link
    rm -f --verbose AliESDs.root
    # Create a symbolic link to the actual AliESDs.root
    ln --verbose -s ${ALIESD_ROOT_FILE} AliESDs.root
    # Run the extraction tool
    aliroot runAnalysis.C

    if [ "$DOWNLOAD" = "false" ]; then

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

    fi

    popd
452
    timestamp "${UNIQUEID}, DATA_ANALYSIS, FINISHED" >> $PROGRESS_LOG
453 454 455 456 457 458 459 460 461 462

  else
    if [ "$DOWNLOAD" = "false" ]; then

      pushd ${ALIROOT_SCRIPT_DIR}
      UNIQUEID=$(more uniqueid.txt)
      echo "The unique ID is $UNIQUEID."
      popd

    fi
463 464
  fi

465
  if ! grep -q "${UNIQUEID}, ANIMATION DIRECTORY CREATED" $PROGRESS_LOG ; then
466 467 468 469

    # Create directory where animations will be saved
    BLENDER_OUTPUT=$(pwd)/$UNIQUEID
    mkdir --verbose -p ${BLENDER_OUTPUT}
470

471
    timestamp "${UNIQUEID}, ANIMATION DIRECTORY CREATED" >> $PROGRESS_LOG
472 473
  else
    BLENDER_OUTPUT=$(pwd)/$UNIQUEID
474 475 476 477
  fi

  pushd ${ALIROOT_SCRIPT_DIR} # push back to aliroot directory

478
  if ! grep -q "${UNIQUEID}, DATA ANALYSIS FILES MOVED to animation directory" $PROGRESS_LOG; then
479 480 481
    #################################################
    # Phase 1: iteration for every event identifier #
    #################################################
482

483 484
    # Get all extracted files
    EXTRACTED_FILES=$(ls -1 esd_detail-event_*.dat | sort --version-sort)
485

486
    for FILE_WITH_DATA in $EXTRACTED_FILES; do
487

488 489
        if ! [[ -s $FILE_WITH_DATA ]]; then
            echo "File $FILE_WITH_DATA has zero size. Ignore and continue."
490
  	        rm -f $FILE_WITH_DATA
491 492
            continue
        fi
493

494 495
        mv ${ALIROOT_SCRIPT_DIR}/$FILE_WITH_DATA \
         ${BLENDER_SCRIPT_DIR}
496

497
    done
498

499
    timestamp "${UNIQUEID}, DATA ANALYSIS FILES MOVED to animation directory" >> $PROGRESS_LOG
500

501
  fi
502

503 504
  popd
  pushd ${BLENDER_SCRIPT_DIR}
505

506
  if ! grep -q "${UNIQUEID}, CREATED EVENT COUNTER FILE" $PROGRESS_LOG; then
507

508
    # Event counter for animating no more events than the informed amount
509
    rm -f event_counter.txt
510 511
    EVENT_COUNTER=0
    echo "$EVENT_COUNTER" > event_counter.txt
512
    timestamp "${UNIQUEID}, CREATED EVENT COUNTER FILE" >> $PROGRESS_LOG
513 514 515

  fi

516
  if ! grep -q "${UNIQUEID}, DATA FILES RENAMED according to UNIQUEID" $PROGRESS_LOG; then
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531

    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 | \
                   sed -e "s#esd_detail-event_##" \
                     -e "s#\.dat##")
        EVENT_UNIQUE_ID=${UNIQUEID}_${EVENT_ID}

        LOCAL_FILE_WITH_DATA=${EVENT_UNIQUE_ID}.dat

        mv $FILE_WITH_DATA $LOCAL_FILE_WITH_DATA

    done
532

533
    timestamp "${UNIQUEID}, DATA FILES RENAMED according to UNIQUEID" >> $PROGRESS_LOG
534

535 536 537 538
  fi

  EXTRACTED_FILES=$(ls -1 ${UNIQUEID}_*.dat | sort --version-sort)

539
  if ! grep -q "${UNIQUEID}, REMOVED UNUSED FILES" $PROGRESS_LOG; then
540

541
    for LOCAL_FILE_WITH_DATA in $EXTRACTED_FILES; do
542

543 544 545
      ##############################
      # Phase 2: Event selection   #
      ##############################
546

547 548
      NUMBER_OF_PARTICLES=$(wc -l $LOCAL_FILE_WITH_DATA | \
                        awk '{ print $1 }')
549

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
      AVERAGE_PZ=$(awk 'BEGIN {pzsum=0;n=0} {pzsum+=$8;n++} END {print sqrt(pzsum*pzsum/n/n)}'\
      ${LOCAL_FILE_WITH_DATA})

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

      echo "File $LOCAL_FILE_WITH_DATA:"
      echo "Number of particles: $NUMBER_OF_PARTICLES"
      echo "Average Z momentum: $AVERAGE_PZ"
      echo "Average transversal momentum $AVERAGE_PT"

      EVENT_COUNTER=$(more event_counter.txt)

      ######################################################################
      # Remove text data of files for events that will not be animated:    #
      ######################################################################
      if (( $(echo "$AVERAGE_PT < $MIN_AVG_PT" |bc -l) )); then

        echo "Average Transversal Momentum too low (minimum accepted is $MIN_AVG_PT). Deleting data text file."

        # Remove non-processed files
        rm -f $LOCAL_FILE_WITH_DATA

      elif (( $(echo "$AVERAGE_PZ < $MIN_AVG_PZ" |bc -l) )); then
574

575
        echo "Average Z Momentum too low (minimum accepted is $MIN_AVG_PZ). Deleting data text file."
576

577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
        # Remove non-processed files
        rm -f $LOCAL_FILE_WITH_DATA

      elif [[ $NUMBER_OF_PARTICLES -lt $MIN_PARTICLES ]]; then

        echo "Too little particles (minimum accepted is $MIN_PARTICLES). Deleting data text file."

        # Remove non-processed files
        rm -f $LOCAL_FILE_WITH_DATA

      elif [[ $NUMBER_OF_PARTICLES -gt $MAX_PARTICLES ]]; then

        echo "Too many particles (maximum accepted is $MAX_PARTICLES). Deleting data text file."

        # Remove non-processed files
        rm -f $LOCAL_FILE_WITH_DATA

      elif [[ $EVENT_COUNTER -ge $N_OF_EVENTS ]]; then

        echo "Numbers of events set to be animated has already been reached. Deleting data text file."

        # Remove non-processed files
        rm -f $LOCAL_FILE_WITH_DATA
      else
601

602 603 604 605
        # Increment event counter
        EVENT_COUNTER=$EVENT_COUNTER+1
        rm -f event_counter.txt
        echo "$EVENT_COUNTER" > event_counter.txt
606

607
        echo "This event will be animated. Continue."
608

609
      fi
610

611
      echo " " # Skip line to make it neat
612

613
    done
614

615
    timestamp "${UNIQUEID}, REMOVED UNUSED FILES" >> $PROGRESS_LOG
616

617
  fi
618

619 620
  # Remove event counter file
  rm -f event_counter.txt
621

622 623 624 625 626 627 628
  if [[ $N_OF_EVENTS = 0 ]]; then
    timestamp "${UNIQUEID}, JOB FINISHED" >> $PROGRESS_LOG
    exit
  else
    # Now the list of extracted files shall only include events we want to animate
    EXTRACTED_FILES=$(ls -1 ${UNIQUEID}_*.dat | sort --version-sort)
  fi
629

630 631 632 633
  ################################################
  #   Create script so we can use GNU parallel   #
  #     to create multiple Blender scenes        #
  ################################################
634
  if ! grep -q "${UNIQUEID}, PARALLEL, SCENES, STARTING" $PROGRESS_LOG; then
635 636

    rm -f scene-making
637 638
    rm -f make-event-*
    rm -f blender-scenes
639 640 641 642 643 644 645

    for LOCAL_FILE_WITH_DATA in $EXTRACTED_FILES; do

      EVENT_ID=$(echo $LOCAL_FILE_WITH_DATA | \
                 sed -e "s#${UNIQUEID}_##" \
                   -e "s#\.dat##")
      EVENT_UNIQUE_ID=${UNIQUEID}_${EVENT_ID}
646 647
      NUMBER_OF_PARTICLES=$(wc -l $LOCAL_FILE_WITH_DATA | \
                        awk '{ print $1 }')
648

649 650 651 652 653 654
      # Write commands for making scene and tracking their progress to separate files "make-event-N"
      echo "# Define a timestamp function" >> make-event-${EVENT_ID}
      echo "timestamp() {" >> make-event-${EVENT_ID}
      echo "  date +\"%y-%m-%d, %T, \$1\"" >> make-event-${EVENT_ID}
      echo "}" >> make-event-${EVENT_ID}
      echo timestamp \"${UNIQUEID}, ${EVENT_ID}, BLENDER SCENE, STARTING, ${NUMBER_OF_PARTICLES}\" \>\> $PROGRESS_LOG >> make-event-${EVENT_ID}
655
      echo blender -noaudio --background -P animate_particles.py -- -radius=${RADIUS} \
656 657 658 659
  -duration=${DURATION} -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} -detailed_tpc=${DETAILED_TPC} \
660
  -blendersave=1 -bgshade=${BGSHADE} -tpc_blender_path=${BLENDER_SCRIPT_DIR} \
661 662 663 664 665 666 667 668
  -output_path=\'${BLENDER_OUTPUT}\' >> make-event-${EVENT_ID}
      echo timestamp \"${UNIQUEID}, ${EVENT_ID}, BLENDER SCENE, FINISHED, ${NUMBER_OF_PARTICLES}\" \>\> $PROGRESS_LOG >> make-event-${EVENT_ID}

      # Write text inside "make-event-N" on common file for all events for registering sake
      more make-event-${EVENT_ID} >> blender-scenes

      # Write command to run code inside "make-event-N" on "scene-making" file
      echo ./make-event-${EVENT_ID} >> scene-making
669
    done
670

671
    timestamp "${UNIQUEID}, PARALLEL, SCENES, STARTING" >> $PROGRESS_LOG
672

673
  fi
674

675 676 677 678
  ###################################
  # Make Blender scenes in parallel #
  ###################################
  if ! grep -q "${UNIQUEID}, PARALLEL, SCENES, FINISHED" $PROGRESS_LOG; then
679

680
    chmod +x make-event-*
681
    parallel < scene-making
682

683
    timestamp "${UNIQUEID}, PARALLEL, SCENES, FINISHED" >> $PROGRESS_LOG
684

685
  fi
686

687
  rm -f scene-making
688 689
  rm -f make-event-*
  mv blender-scenes ${BLENDER_OUTPUT}/blender-scenes
690

691 692 693 694
  #####################################
  # Render scenes in selected cameras #
  #####################################
  for LOCAL_FILE_WITH_DATA in $EXTRACTED_FILES; do
695

696 697 698 699 700 701
    EVENT_ID=$(echo $LOCAL_FILE_WITH_DATA | \
               sed -e "s#${UNIQUEID}_##" \
                 -e "s#\.dat##")
    EVENT_UNIQUE_ID=${UNIQUEID}_${EVENT_ID}
    NUMBER_OF_PARTICLES=$(wc -l $LOCAL_FILE_WITH_DATA | \
                      awk '{ print $1 }')
702

703
    for type in $CAMERAS; do
704

705
      if ! grep -q "${UNIQUEID}, ${EVENT_ID}, ${type}, FINISHED" $PROGRESS_LOG; then
706

707 708 709
        timestamp "${UNIQUEID}, ${EVENT_ID}, ${type}, STARTING, $NUMBER_OF_PARTICLES" >> $PROGRESS_LOG
        blender -noaudio --background -P render.py -- -cam ${type} -datafile\
         "${LOCAL_FILE_WITH_DATA}" -n_event ${EVENT_ID} -pic_pct ${PICPCT} -output_path "${BLENDER_OUTPUT}"
710

711
        timestamp "${UNIQUEID}, ${EVENT_ID}, ${type}, FINISHED, $NUMBER_OF_PARTICLES" >> $PROGRESS_LOG
712

713
      fi
714

715
    done
716

717 718 719 720
    ########################
    # Make mosaic 2x2 clip #
    ########################
    if [ "$MOSAIC" = "true" ]; then
721

722 723
      if ! grep -q "${UNIQUEID}, ${EVENT_ID}, MOSAIC, FINISHED" $PROGRESS_LOG; then
        pushd ${BLENDER_OUTPUT}
724

725
        timestamp "${UNIQUEID}, ${EVENT_ID}, MOSAIC, STARTING, $NUMBER_OF_PARTICLES" >> $PROGRESS_LOG
726

727 728 729
        # Delete existing incomplete .mp4 file
        if [[ -f ${EVENT_UNIQUE_ID}_Mosaic.mp4 ]]; then
          rm ${EVENT_UNIQUE_ID}_Mosaic.mp4
730
        fi
731

732 733 734 735 736 737 738 739 740 741 742 743 744
        # Setting input names for clips in order to make mosaic clip
        INPUT_ONE=$(ls *$EVENT_UNIQUE_ID*${FPS_DUR}.mp4 | awk 'NR==1')
        INPUT_TWO=$(ls *$EVENT_UNIQUE_ID*${FPS_DUR}.mp4 | awk 'NR==2')
        INPUT_THREE=$(ls *$EVENT_UNIQUE_ID*${FPS_DUR}.mp4 | awk 'NR==3')
        INPUT_FOUR=$(ls *$EVENT_UNIQUE_ID*${FPS_DUR}.mp4 | 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

        timestamp "${UNIQUEID}, ${EVENT_ID}, MOSAIC, FINISHED, $NUMBER_OF_PARTICLES" >> $PROGRESS_LOG

        popd
745
      fi
746 747 748

    fi

749 750 751 752
    #######################################################
    # Move text data files to where animations are stored #
    #######################################################
    if ! grep -q "${UNIQUEID}, ${EVENT_ID}, TEXT DATA MOVED to final location" $PROGRESS_LOG; then
753

754 755 756
      # Move processed file to final location
      mv $LOCAL_FILE_WITH_DATA ${BLENDER_OUTPUT}/$LOCAL_FILE_WITH_DATA
      timestamp "${UNIQUEID}, ${EVENT_ID}, TEXT DATA MOVED to final location" >> $PROGRESS_LOG
757

758 759 760 761 762
    fi

    echo "EVENT ${EVENT_UNIQUE_ID} DONE with FILE $LOCAL_FILE_WITH_DATA."

  done
763
  popd
764

765 766 767 768 769 770 771 772 773
  ########################
  # Remove blender files #
  ########################
  if [[ $BLENDERSAVE = 0 ]]; then
    pushd ${BLENDER_OUTPUT}
    rm -f *.blend
    popd
  fi

774
fi
775
timestamp "${UNIQUEID}, JOB FINISHED" >> $PROGRESS_LOG