From e75c7ab8d3ed8668cbc125c8dab51fae40369c39 Mon Sep 17 00:00:00 2001 From: gong1 <b.gong@fz-juelich.de> Date: Tue, 15 Sep 2020 14:13:37 +0200 Subject: [PATCH] remove useless files and move files to new structure --- .../HPC_scripts/hyperparam_setup.sh | 12 - .../HPC_scripts/reset_dirs.sh | 11 - .../bash/download_and_preprocess_dataset.sh | 88 -- .../download_and_preprocess_dataset_era5.sh | 127 --- .../download_and_preprocess_dataset_v1.sh | 86 -- video_prediction_savp/bash/workflow_era5.sh | 92 -- .../bash/workflow_era5_macOS.sh | 93 -- .../bash/workflow_era5_zam347.sh | 93 -- .../{ => deprecate}/helper/helper.py | 0 .../pretrained_models/download_model.sh | 0 .../scripts/combine_results.py | 0 .../{ => deprecate}/scripts/evaluate.py | 0 .../{ => deprecate}/scripts/evaluate_all.sh | 0 .../{ => deprecate}/scripts/generate_all.sh | 0 .../{ => deprecate}/scripts/generate_orig.py | 0 .../{ => deprecate}/scripts/plot_results.py | 0 .../scripts/plot_results_all.sh | 0 .../{ => deprecate}/scripts/train.py | 0 .../{ => deprecate}/scripts/train_all.sh | 0 .../docs/presentation/presentation.md | 5 - video_prediction_savp/scripts/Analysis_all.py | 105 --- video_prediction_savp/scripts/evaluate_svg.sh | 1 - video_prediction_savp/scripts/generate.py | 537 ------------ .../scripts}/mpi_stager_v2.py | 0 .../scripts}/mpi_stager_v2_process_netCDF.py | 0 video_prediction_savp/scripts/train_v2.py | 362 -------- .../utils}/external_function.py | 0 .../utils}/shiftgrid.py | 0 .../datasets}/prepare_era5_data.py | 0 .../datasets}/process_netCDF_v2.py | 0 .../DataExtraction/helper_single_master.py | 245 ------ .../DataExtraction/main_single_master.py | 257 ------ .../DataExtraction/readme.md | 2 - .../DataExtraction/submitJob.sh | 22 - .../Stager_devel_N_24_evaluation.sh | 40 - .../DataPostprocess/data_utils.py | 164 ---- .../DataPostprocess/keras_utils.py | 58 -- .../kitti_evaluate_parallel.py | 159 ---- .../DataPostprocess/kitti_settings.py | 19 - .../DataPostprocess/packageInstallation.sh | 9 - .../parameters_kitti_evaluate.dat | 14 - .../DataPostprocess/prednet.py | 311 ------- .../Stager_devel_N_24_process_netCDF.sh | 22 - .../DataPreprocess/external_function.py | 158 ---- .../mpi_split_data_multi_years.py | 58 -- workflow_parallel_frame_prediction/README.md | 56 -- .../Training/data_utils.py | 163 ---- .../Training/devel_horovodJob.sh | 43 - .../Training/evaluate_multistep.py | 121 --- .../Training/hickle/bin/f2py | 4 - .../__pycache__/site.cpython-36.pyc | Bin 1482 -> 0 bytes .../python3.6/site-packages/easy-install.pth | 4 - .../hickle-3.4.3-py3.6.egg/EGG-INFO/PKG-INFO | 207 ----- .../EGG-INFO/SOURCES.txt | 52 -- .../EGG-INFO/dependency_links.txt | 1 - .../EGG-INFO/not-zip-safe | 1 - .../EGG-INFO/requires.txt | 2 - .../EGG-INFO/top_level.txt | 2 - .../hickle-3.4.3-py3.6.egg/hickle/__init__.py | 4 - .../__pycache__/__init__.cpython-36.pyc | Bin 278 -> 0 bytes .../hickle/__pycache__/helpers.cpython-36.pyc | Bin 3266 -> 0 bytes .../hickle/__pycache__/hickle.cpython-36.pyc | Bin 17742 -> 0 bytes .../__pycache__/hickle_legacy.cpython-36.pyc | Bin 14836 -> 0 bytes .../__pycache__/hickle_legacy2.cpython-36.pyc | Bin 20746 -> 0 bytes .../hickle/__pycache__/lookup.cpython-36.pyc | Bin 6661 -> 0 bytes .../hickle-3.4.3-py3.6.egg/hickle/helpers.py | 113 --- .../hickle-3.4.3-py3.6.egg/hickle/hickle.py | 611 ------------- .../hickle/hickle_legacy.py | 535 ------------ .../hickle/hickle_legacy2.py | 672 -------------- .../hickle/loaders/__init__.py | 1 - .../__pycache__/__init__.cpython-36.pyc | Bin 252 -> 0 bytes .../__pycache__/load_astropy.cpython-36.pyc | Bin 7453 -> 0 bytes .../__pycache__/load_numpy.cpython-36.pyc | Bin 4199 -> 0 bytes .../__pycache__/load_pandas.cpython-36.pyc | Bin 249 -> 0 bytes .../__pycache__/load_python.cpython-36.pyc | Bin 4349 -> 0 bytes .../__pycache__/load_python3.cpython-36.pyc | Bin 5988 -> 0 bytes .../__pycache__/load_scipy.cpython-36.pyc | Bin 3032 -> 0 bytes .../hickle/loaders/load_astropy.py | 237 ----- .../hickle/loaders/load_numpy.py | 145 --- .../hickle/loaders/load_pandas.py | 4 - .../hickle/loaders/load_python.py | 141 --- .../hickle/loaders/load_python3.py | 201 ----- .../hickle/loaders/load_scipy.py | 92 -- .../hickle-3.4.3-py3.6.egg/hickle/lookup.py | 238 ----- .../hickle-3.4.3-py3.6.egg/tests/__init__.py | 0 .../tests/__pycache__/__init__.cpython-36.pyc | Bin 209 -> 0 bytes .../__pycache__/test_astropy.cpython-36.pyc | Bin 3798 -> 0 bytes .../__pycache__/test_hickle.cpython-36.pyc | Bin 18861 -> 0 bytes .../test_hickle_helpers.cpython-36.pyc | Bin 1969 -> 0 bytes .../test_legacy_load.cpython-36.pyc | Bin 840 -> 0 bytes .../__pycache__/test_scipy.cpython-36.pyc | Bin 1718 -> 0 bytes .../tests/test_astropy.py | 133 --- .../tests/test_hickle.py | 826 ------------------ .../tests/test_hickle_helpers.py | 63 -- .../tests/test_legacy_load.py | 30 - .../tests/test_scipy.py | 57 -- .../lib/python3.6/site-packages/site.py | 74 -- .../Training/horovodJob.sh | 44 - .../Training/keras_utils.py | 58 -- .../Training/kitti_settings.py | 19 - .../Training/kitti_train_horovod.py | 119 --- .../Training/minMaxExtractor.py | 76 -- .../Training/prednet.py | 311 ------- .../Training/process_netCDF.py | 169 ---- .../Workflow.png | Bin 195317 -> 0 bytes .../__init__.py | 0 workflow_parallel_frame_prediction/main.sh | 28 - workflow_parallel_frame_prediction/setup.py | 11 - 108 files changed, 8818 deletions(-) delete mode 100644 video_prediction_savp/HPC_scripts/hyperparam_setup.sh delete mode 100644 video_prediction_savp/HPC_scripts/reset_dirs.sh delete mode 100644 video_prediction_savp/bash/download_and_preprocess_dataset.sh delete mode 100644 video_prediction_savp/bash/download_and_preprocess_dataset_era5.sh delete mode 100644 video_prediction_savp/bash/download_and_preprocess_dataset_v1.sh delete mode 100755 video_prediction_savp/bash/workflow_era5.sh delete mode 100755 video_prediction_savp/bash/workflow_era5_macOS.sh delete mode 100755 video_prediction_savp/bash/workflow_era5_zam347.sh rename video_prediction_savp/{ => deprecate}/helper/helper.py (100%) rename video_prediction_savp/{ => deprecate}/pretrained_models/download_model.sh (100%) rename video_prediction_savp/{ => deprecate}/scripts/combine_results.py (100%) rename video_prediction_savp/{ => deprecate}/scripts/evaluate.py (100%) rename video_prediction_savp/{ => deprecate}/scripts/evaluate_all.sh (100%) rename video_prediction_savp/{ => deprecate}/scripts/generate_all.sh (100%) rename video_prediction_savp/{ => deprecate}/scripts/generate_orig.py (100%) rename video_prediction_savp/{ => deprecate}/scripts/plot_results.py (100%) rename video_prediction_savp/{ => deprecate}/scripts/plot_results_all.sh (100%) rename video_prediction_savp/{ => deprecate}/scripts/train.py (100%) rename video_prediction_savp/{ => deprecate}/scripts/train_all.sh (100%) delete mode 100644 video_prediction_savp/docs/presentation/presentation.md delete mode 100644 video_prediction_savp/scripts/Analysis_all.py delete mode 100644 video_prediction_savp/scripts/evaluate_svg.sh delete mode 100644 video_prediction_savp/scripts/generate.py rename {workflow_parallel_frame_prediction/DataExtraction => video_prediction_savp/scripts}/mpi_stager_v2.py (100%) rename {workflow_parallel_frame_prediction/DataPreprocess => video_prediction_savp/scripts}/mpi_stager_v2_process_netCDF.py (100%) delete mode 100644 video_prediction_savp/scripts/train_v2.py rename {workflow_parallel_frame_prediction/DataExtraction => video_prediction_savp/utils}/external_function.py (100%) rename {workflow_parallel_frame_prediction/DataExtraction => video_prediction_savp/utils}/shiftgrid.py (100%) rename {workflow_parallel_frame_prediction/DataExtraction => video_prediction_savp/video_prediction/datasets}/prepare_era5_data.py (100%) rename {workflow_parallel_frame_prediction/DataPreprocess => video_prediction_savp/video_prediction/datasets}/process_netCDF_v2.py (100%) delete mode 100644 workflow_parallel_frame_prediction/DataExtraction/helper_single_master.py delete mode 100644 workflow_parallel_frame_prediction/DataExtraction/main_single_master.py delete mode 100644 workflow_parallel_frame_prediction/DataExtraction/readme.md delete mode 100755 workflow_parallel_frame_prediction/DataExtraction/submitJob.sh delete mode 100755 workflow_parallel_frame_prediction/DataPostprocess/Stager_devel_N_24_evaluation.sh delete mode 100755 workflow_parallel_frame_prediction/DataPostprocess/data_utils.py delete mode 100755 workflow_parallel_frame_prediction/DataPostprocess/keras_utils.py delete mode 100755 workflow_parallel_frame_prediction/DataPostprocess/kitti_evaluate_parallel.py delete mode 100755 workflow_parallel_frame_prediction/DataPostprocess/kitti_settings.py delete mode 100644 workflow_parallel_frame_prediction/DataPostprocess/packageInstallation.sh delete mode 100755 workflow_parallel_frame_prediction/DataPostprocess/parameters_kitti_evaluate.dat delete mode 100755 workflow_parallel_frame_prediction/DataPostprocess/prednet.py delete mode 100755 workflow_parallel_frame_prediction/DataPreprocess/Stager_devel_N_24_process_netCDF.sh delete mode 100755 workflow_parallel_frame_prediction/DataPreprocess/external_function.py delete mode 100644 workflow_parallel_frame_prediction/DataPreprocess/mpi_split_data_multi_years.py delete mode 100755 workflow_parallel_frame_prediction/README.md delete mode 100755 workflow_parallel_frame_prediction/Training/data_utils.py delete mode 100644 workflow_parallel_frame_prediction/Training/devel_horovodJob.sh delete mode 100644 workflow_parallel_frame_prediction/Training/evaluate_multistep.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/bin/f2py delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/__pycache__/site.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/easy-install.pth delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/PKG-INFO delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/SOURCES.txt delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/dependency_links.txt delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/not-zip-safe delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/requires.txt delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/top_level.txt delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__init__.py delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/__init__.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/helpers.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle_legacy.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle_legacy2.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/lookup.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/helpers.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy2.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__init__.py delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/__init__.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_astropy.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_numpy.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_pandas.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_python.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_python3.cpython-36.pyc delete mode 100644 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_scipy.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_astropy.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_numpy.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_pandas.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python3.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_scipy.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/lookup.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__init__.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/__init__.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_astropy.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_hickle.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_hickle_helpers.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_legacy_load.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_scipy.cpython-36.pyc delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_astropy.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle_helpers.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_legacy_load.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_scipy.py delete mode 100755 workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/site.py delete mode 100644 workflow_parallel_frame_prediction/Training/horovodJob.sh delete mode 100755 workflow_parallel_frame_prediction/Training/keras_utils.py delete mode 100755 workflow_parallel_frame_prediction/Training/kitti_settings.py delete mode 100755 workflow_parallel_frame_prediction/Training/kitti_train_horovod.py delete mode 100644 workflow_parallel_frame_prediction/Training/minMaxExtractor.py delete mode 100755 workflow_parallel_frame_prediction/Training/prednet.py delete mode 100644 workflow_parallel_frame_prediction/Training/process_netCDF.py delete mode 100644 workflow_parallel_frame_prediction/Workflow.png delete mode 100755 workflow_parallel_frame_prediction/__init__.py delete mode 100644 workflow_parallel_frame_prediction/main.sh delete mode 100755 workflow_parallel_frame_prediction/setup.py diff --git a/video_prediction_savp/HPC_scripts/hyperparam_setup.sh b/video_prediction_savp/HPC_scripts/hyperparam_setup.sh deleted file mode 100644 index 34894da8..00000000 --- a/video_prediction_savp/HPC_scripts/hyperparam_setup.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -# for choosing the model convLSTM vae mcnet savp -export model=convLSTM -export model_hparams=../hparams/era5/${model}/model_hparams.json - -#create a subfolder with create time and user names, which can be consider as hyperparameter tunning folder. This can avoid overwrite the prevoius trained model using differ#ent hypermeters -export hyperdir="$(date +"%Y%m%dT%H%M")_"$USER"" - -echo "model: ${model}" -echo "hparams: ${model_hparams}" -echo "experiment dir: ${hyperdir}" diff --git a/video_prediction_savp/HPC_scripts/reset_dirs.sh b/video_prediction_savp/HPC_scripts/reset_dirs.sh deleted file mode 100644 index 8de5247e..00000000 --- a/video_prediction_savp/HPC_scripts/reset_dirs.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -sed -i "s|source_dir=.*|source_dir=${SAVE_DIR}preprocessedData/|g" DataPreprocess_to_tf.sh -sed -i "s|destination_dir=.*|destination_dir=${SAVE_DIR}preprocessedData/|g" DataPreprocess_to_tf.sh - -sed -i "s|source_dir=.*|source_dir=${SAVE_DIR}preprocessedData/|g" train_era5.sh -sed -i "s|destination_dir=.*|destination_dir=${SAVE_DIR}models/|g" train_era5.sh - -sed -i "s|source_dir=.*|source_dir=${SAVE_DIR}preprocessedData/|g" generate_era5.sh -sed -i "s|checkpoint_dir=.*|checkpoint_dir=${SAVE_DIR}models/|g" generate_era5.sh -sed -i "s|results_dir=.*|results_dir=${SAVE_DIR}results/|g" generate_era5.sh diff --git a/video_prediction_savp/bash/download_and_preprocess_dataset.sh b/video_prediction_savp/bash/download_and_preprocess_dataset.sh deleted file mode 100644 index 5779c2b7..00000000 --- a/video_prediction_savp/bash/download_and_preprocess_dataset.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash - -# exit if any command fails -set -e - -if [ "$#" -eq 2 ]; then - if [ $1 = "bair" ]; then - echo "IMAGE_SIZE argument is only applicable to kth dataset" >&2 - exit 1 - fi -elif [ "$#" -ne 1 ]; then - echo "Usage: $0 DATASET_NAME [IMAGE_SIZE]" >&2 - exit 1 -fi -if [ $1 = "bair" ]; then - TARGET_DIR=./data/bair - mkdir -p ${TARGET_DIR} - TAR_FNAME=bair_robot_pushing_dataset_v0.tar - URL=http://rail.eecs.berkeley.edu/datasets/${TAR_FNAME} - echo "Downloading '$1' dataset (this takes a while)" - #wget ${URL} -O ${TARGET_DIR}/${TAR_FNAME} Bing: on MacOS system , use curl instead of wget - curl ${URL} -O ${TARGET_DIR}/${TAR_FNAME} - tar -xvf ${TARGET_DIR}/${TAR_FNAME} --strip-components=1 -C ${TARGET_DIR} - rm ${TARGET_DIR}/${TAR_FNAME} - mkdir -p ${TARGET_DIR}/val - # reserve a fraction of the training set for validation - mv ${TARGET_DIR}/train/traj_256_to_511.tfrecords ${TARGET_DIR}/val/ -elif [ $1 = "kth" ]; then - if [ "$#" -eq 2 ]; then - IMAGE_SIZE=$2 - TARGET_DIR=./data/kth_${IMAGE_SIZE} - else - IMAGE_SIZE=64 - TARGET_DIR=./data/kth - fi - echo ${TARGET_DIR} ${IMAGE_SIZE} - mkdir -p ${TARGET_DIR} - mkdir -p ${TARGET_DIR}/raw - echo "Downloading '$1' dataset (this takes a while)" - # TODO Bing: for save time just use walking, need to change back if all the data are needed - #for ACTION in walking jogging running boxing handwaving handclapping; do -# for ACTION in walking; do -# echo "Action: '$ACTION' " -# ZIP_FNAME=${ACTION}.zip -# URL=http://www.nada.kth.se/cvap/actions/${ZIP_FNAME} -# # wget ${URL} -O ${TARGET_DIR}/raw/${ZIP_FNAME} -# echo "Start downloading action '$ACTION' ULR '$URL' " -# curl ${URL} -O ${TARGET_DIR}/raw/${ZIP_FNAME} -# unzip ${TARGET_DIR}/raw/${ZIP_FNAME} -d ${TARGET_DIR}/raw/${ACTION} -# echo "Action '$ACTION' data download and unzip " -# done - FRAME_RATE=25 -# mkdir -p ${TARGET_DIR}/processed -# # download files with metadata specifying the subsequences -# TAR_FNAME=kth_meta.tar.gz -# URL=http://rail.eecs.berkeley.edu/models/savp/data/${TAR_FNAME} -# echo "Downloading '${TAR_FNAME}' ULR '$URL' " -# #wget ${URL} -O ${TARGET_DIR}/processed/${TAR_FNAME} -# curl ${URL} -O ${TARGET_DIR}/processed/${TAR_FNAME} -# tar -xzvf ${TARGET_DIR}/processed/${TAR_FNAME} --strip 1 -C ${TARGET_DIR}/processed - # convert the videos into sequence of downscaled images - echo "Processing '$1' dataset" - #TODO Bing, just use walking for test - #for ACTION in walking jogging running boxing handwaving handclapping; do - #Todo Bing: remove the comments below after testing - for ACTION in walking running; do - for VIDEO_FNAME in ${TARGET_DIR}/raw/${ACTION}/*.avi; do - FNAME=$(basename ${VIDEO_FNAME}) - FNAME=${FNAME%_uncomp.avi} - echo "FNAME '$FNAME' " - # sometimes the directory is not created, so try until it is - while [ ! -d "${TARGET_DIR}/processed/${ACTION}/${FNAME}" ]; do - mkdir -p ${TARGET_DIR}/processed/${ACTION}/${FNAME} - done - ffmpeg -i ${VIDEO_FNAME} -r ${FRAME_RATE} -f image2 -s ${IMAGE_SIZE}x${IMAGE_SIZE} \ - ${TARGET_DIR}/processed/${ACTION}/${FNAME}/image-%03d_${IMAGE_SIZE}x${IMAGE_SIZE}.png - done - done - python video_prediction/datasets/kth_dataset.py ${TARGET_DIR}/processed ${TARGET_DIR} ${IMAGE_SIZE} - rm -rf ${TARGET_DIR}/raw - rm -rf ${TARGET_DIR}/processed -else - echo "Invalid dataset name: '$1' (choose from 'bair', 'kth')" >&2 - exit 1 -fi -echo "Succesfully finished downloadi\ - -ng and preprocessing dataset '$1'" diff --git a/video_prediction_savp/bash/download_and_preprocess_dataset_era5.sh b/video_prediction_savp/bash/download_and_preprocess_dataset_era5.sh deleted file mode 100644 index eacc0180..00000000 --- a/video_prediction_savp/bash/download_and_preprocess_dataset_era5.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bash - -# exit if any command fails -set -e - - -#if [ "$#" -eq 2 ]; then -# if [ $1 = "bair" ]; then -# echo "IMAGE_SIZE argument is only applicable to kth dataset" >&2 -# exit 1 -# fi -#elif [ "$#" -ne 1 ]; then -# echo "Usage: $0 DATASET_NAME [IMAGE_SIZE]" >&2 -# exit 1 -#fi -#if [ $1 = "bair" ]; then -# TARGET_DIR=./data/bair -# mkdir -p ${TARGET_DIR} -# TAR_FNAME=bair_robot_pushing_dataset_v0.tar -# URL=http://rail.eecs.berkeley.edu/datasets/${TAR_FNAME} -# echo "Downloading '$1' dataset (this takes a while)" -# #wget ${URL} -O ${TARGET_DIR}/${TAR_FNAME} Bing: on MacOS system , use curl instead of wget -# curl ${URL} -O ${TARGET_DIR}/${TAR_FNAME} -# tar -xvf ${TARGET_DIR}/${TAR_FNAME} --strip-components=1 -C ${TARGET_DIR} -# rm ${TARGET_DIR}/${TAR_FNAME} -# mkdir -p ${TARGET_DIR}/val -# # reserve a fraction of the training set for validation -# mv ${TARGET_DIR}/train/traj_256_to_511.tfrecords ${TARGET_DIR}/val/ -#elif [ $1 = "kth" ]; then -# if [ "$#" -eq 2 ]; then -# IMAGE_SIZE=$2 -# TARGET_DIR=./data/kth_${IMAGE_SIZE} -# else -# IMAGE_SIZE=64 -# fi -# echo ${TARGET_DIR} ${IMAGE_SIZE} -# mkdir -p ${TARGET_DIR} -# mkdir -p ${TARGET_DIR}/raw -# echo "Downloading '$1' dataset (this takes a while)" - # TODO Bing: for save time just use walking, need to change back if all the data are needed - #for ACTION in walking jogging running boxing handwaving handclapping; do -# for ACTION in walking; do -# echo "Action: '$ACTION' " -# ZIP_FNAME=${ACTION}.zip -# URL=http://www.nada.kth.se/cvap/actions/${ZIP_FNAME} -# # wget ${URL} -O ${TARGET_DIR}/raw/${ZIP_FNAME} -# echo "Start downloading action '$ACTION' ULR '$URL' " -# curl ${URL} -O ${TARGET_DIR}/raw/${ZIP_FNAME} -# unzip ${TARGET_DIR}/raw/${ZIP_FNAME} -d ${TARGET_DIR}/raw/${ACTION} -# echo "Action '$ACTION' data download and unzip " -# done -# FRAME_RATE=25 -# mkdir -p ${TARGET_DIR}/processed -# # download files with metadata specifying the subsequences -# TAR_FNAME=kth_meta.tar.gz -# URL=http://rail.eecs.berkeley.edu/models/savp/data/${TAR_FNAME} -# echo "Downloading '${TAR_FNAME}' ULR '$URL' " -# #wget ${URL} -O ${TARGET_DIR}/processed/${TAR_FNAME} -# curl ${URL} -O ${TARGET_DIR}/processed/${TAR_FNAME} -# tar -xzvf ${TARGET_DIR}/processed/${TAR_FNAME} --strip 1 -C ${TARGET_DIR}/processed - # convert the videos into sequence of downscaled images -# echo "Processing '$1' dataset" -# #TODO Bing, just use walking for test -# #for ACTION in walking jogging running boxing handwaving handclapping; do -# #Todo Bing: remove the comments below after testing -# for ACTION in walking; do -# for VIDEO_FNAME in ${TARGET_DIR}/raw/${ACTION}/*.avi; do -# FNAME=$(basename ${VIDEO_FNAME}) -# FNAME=${FNAME%_uncomp.avi} -# echo "FNAME '$FNAME' " -# # sometimes the directory is not created, so try until it is -# while [ ! -d "${TARGET_DIR}/processed/${ACTION}/${FNAME}" ]; do -# mkdir -p ${TARGET_DIR}/processed/${ACTION}/${FNAME} -# done -# ffmpeg -i ${VIDEO_FNAME} -r ${FRAME_RATE} -f image2 -s ${IMAGE_SIZE}x${IMAGE_SIZE} \ -# ${TARGET_DIR}/processed/${ACTION}/${FNAME}/image-%03d_${IMAGE_SIZE}x${IMAGE_SIZE}.png -# done -# done -# python video_prediction/datasets/kth_dataset.py ${TARGET_DIR}/processed ${TARGET_DIR} ${IMAGE_SIZE} -# rm -rf ${TARGET_DIR}/raw -# rm -rf ${TARGET_DIR}/processed - -while [[ $# -gt 0 ]] #of the number of passed argument is greater than 0 -do -key="$1" -case $key in - -d|--data) - DATA="$2" - shift - shift - ;; - -i|--input_dir) - INPUT_DIR="$2" - shift - shift - ;; - -o|--output_dir) - OUTPUT_DIR="$2" - shift - shift - ;; -esac -done - -echo "DATA = ${DATA} " - -echo "OUTPUT_DIRECTORY = ${OUTPUT_DIR}" - -if [ -d $INPUT_DIR ]; then - echo "INPUT DIRECTORY = ${INPUT_DIR}" - -else - echo "INPUT DIRECTORY '$INPUT_DIR' DOES NOT EXIST" - exit 1 -fi - - -if [ $DATA = "era5" ]; then - - mkdir -p ${OUTPUT_DIR} - python video_prediction/datasets/era5_dataset.py $INPUT_DIR ${OUTPUT_DIR} -else - echo "dataset name: '$DATA' (choose from 'era5')" >&2 - exit 1 -fi - -echo "Succesfully finished downloading and preprocessing dataset '$DATA' " \ No newline at end of file diff --git a/video_prediction_savp/bash/download_and_preprocess_dataset_v1.sh b/video_prediction_savp/bash/download_and_preprocess_dataset_v1.sh deleted file mode 100644 index 3541b4a5..00000000 --- a/video_prediction_savp/bash/download_and_preprocess_dataset_v1.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env bash - -# exit if any command fails -set -e - -if [ "$#" -eq 2 ]; then - if [ $1 = "bair" ]; then - echo "IMAGE_SIZE argument is only applicable to kth dataset" >&2 - exit 1 - fi -elif [ "$#" -ne 1 ]; then - echo "Usage: $0 DATASET_NAME [IMAGE_SIZE]" >&2 - exit 1 -fi -if [ $1 = "bair" ]; then - TARGET_DIR=./data/bair - mkdir -p ${TARGET_DIR} - TAR_FNAME=bair_robot_pushing_dataset_v0.tar - URL=http://rail.eecs.berkeley.edu/datasets/${TAR_FNAME} - echo "Downloading '$1' dataset (this takes a while)" - #wget ${URL} -O ${TARGET_DIR}/${TAR_FNAME} Bing: on MacOS system , use curl instead of wget - curl ${URL} -O ${TARGET_DIR}/${TAR_FNAME} - tar -xvf ${TARGET_DIR}/${TAR_FNAME} --strip-components=1 -C ${TARGET_DIR} - rm ${TARGET_DIR}/${TAR_FNAME} - mkdir -p ${TARGET_DIR}/val - # reserve a fraction of the training set for validation - mv ${TARGET_DIR}/train/traj_256_to_511.tfrecords ${TARGET_DIR}/val/ -elif [ $1 = "kth" ]; then - if [ "$#" -eq 2 ]; then - IMAGE_SIZE=$2 - TARGET_DIR=./data/kth_${IMAGE_SIZE} - else - IMAGE_SIZE=64 - TARGET_DIR=./data/kth - fi - echo ${TARGET_DIR} ${IMAGE_SIZE} - mkdir -p ${TARGET_DIR} - mkdir -p ${TARGET_DIR}/raw - echo "Downloading '$1' dataset (this takes a while)" - # TODO Bing: for save time just use walking, need to change back if all the data are needed - #for ACTION in walking jogging running boxing handwaving handclapping; do -# for ACTION in walking; do -# echo "Action: '$ACTION' " -# ZIP_FNAME=${ACTION}.zip -# URL=http://www.nada.kth.se/cvap/actions/${ZIP_FNAME} -# # wget ${URL} -O ${TARGET_DIR}/raw/${ZIP_FNAME} -# echo "Start downloading action '$ACTION' ULR '$URL' " -# curl ${URL} -O ${TARGET_DIR}/raw/${ZIP_FNAME} -# unzip ${TARGET_DIR}/raw/${ZIP_FNAME} -d ${TARGET_DIR}/raw/${ACTION} -# echo "Action '$ACTION' data download and unzip " -# done - FRAME_RATE=25 -# mkdir -p ${TARGET_DIR}/processed -# # download files with metadata specifying the subsequences -# TAR_FNAME=kth_meta.tar.gz -# URL=http://rail.eecs.berkeley.edu/models/savp/data/${TAR_FNAME} -# echo "Downloading '${TAR_FNAME}' ULR '$URL' " -# #wget ${URL} -O ${TARGET_DIR}/processed/${TAR_FNAME} -# curl ${URL} -O ${TARGET_DIR}/processed/${TAR_FNAME} -# tar -xzvf ${TARGET_DIR}/processed/${TAR_FNAME} --strip 1 -C ${TARGET_DIR}/processed - # convert the videos into sequence of downscaled images - echo "Processing '$1' dataset" - #TODO Bing, just use walking for test - #for ACTION in walking jogging running boxing handwaving handclapping; do - #Todo Bing: remove the comments below after testing - for ACTION in walking; do - for VIDEO_FNAME in ${TARGET_DIR}/raw/${ACTION}/*.avi; do - FNAME=$(basename ${VIDEO_FNAME}) - FNAME=${FNAME%_uncomp.avi} - echo "FNAME '$FNAME' " - # sometimes the directory is not created, so try until it is - while [ ! -d "${TARGET_DIR}/processed/${ACTION}/${FNAME}" ]; do - mkdir -p ${TARGET_DIR}/processed/${ACTION}/${FNAME} - done - ffmpeg -i ${VIDEO_FNAME} -r ${FRAME_RATE} -f image2 -s ${IMAGE_SIZE}x${IMAGE_SIZE} \ - ${TARGET_DIR}/processed/${ACTION}/${FNAME}/image-%03d_${IMAGE_SIZE}x${IMAGE_SIZE}.png - done - done - python video_prediction/datasets/kth_dataset.py ${TARGET_DIR}/processed ${TARGET_DIR} ${IMAGE_SIZE} - rm -rf ${TARGET_DIR}/raw - rm -rf ${TARGET_DIR}/processed -else - echo "Invalid dataset name: '$1' (choose from 'bair', 'kth')" >&2 - exit 1 -fi -echo "Succesfully finished downloading and preprocessing dataset '$1'" diff --git a/video_prediction_savp/bash/workflow_era5.sh b/video_prediction_savp/bash/workflow_era5.sh deleted file mode 100755 index 01d16bfd..00000000 --- a/video_prediction_savp/bash/workflow_era5.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env bash -set -e -# -#MODEL=savp -##train_mode: end_to_end, pre_trained -#TRAIN_MODE=end_to_end -#EXP_NAME=era5_size_64_64_3_3t_norm - -MODEL=$1 -TRAIN_MODE=$2 -EXP_NAME=$3 -RETRAIN=1 #if we continue training the model or using the existing end-to-end model, 1 means continue training, and 1 means use the existing one -DATA_ETL_DIR=/p/scratch/deepacf/${USER}/ -DATA_EXTRA_DIR=${DATA_ETL_DIR}/extractedData/${EXP_NAME} -DATA_PREPROCESS_DIR=${DATA_ETL_DIR}/preprocessedData/${EXP_NAME} -DATA_PREPROCESS_TF_DIR=./data/${EXP_NAME} -RESULTS_OUTPUT_DIR=./results_test_samples/${EXP_NAME}/${TRAIN_MODE}/ - -if [ $MODEL==savp ]; then - method_dir=ours_savp -elif [ $MODEL==gan ]; then - method_dir=ours_gan -elif [ $MODEL==vae ]; then - method_dir=ours_vae -else - echo "model does not exist" 2>&1 - exit 1 -fi - -if [ "$TRAIN_MODE" == pre_trained ]; then - TRAIN_OUTPUT_DIR=./pretrained_models/kth/${method_dir} -else - TRAIN_OUTPUT_DIR=./logs/${EXP_NAME}/${TRAIN_MODE} -fi - -CHECKPOINT_DIR=${TRAIN_OUTPUT_DIR}/${method_dir} - -echo "===========================WORKFLOW SETUP====================" -echo "Model ${MODEL}" -echo "TRAIN MODE ${TRAIN_MODE}" -echo "Method_dir ${method_dir}" -echo "DATA_ETL_DIR ${DATA_ETL_DIR}" -echo "DATA_EXTRA_DIR ${DATA_EXTRA_DIR}" -echo "DATA_PREPROCESS_DIR ${DATA_PREPROCESS_DIR}" -echo "DATA_PREPROCESS_TF_DIR ${DATA_PREPROCESS_TF_DIR}" -echo "TRAIN_OUTPUT_DIR ${TRAIN_OUTPUT_DIR}" -echo "=============================================================" - -##############Datat Preprocessing################ -#To hkl data -if [ -d "$DATA_PREPROCESS_DIR" ]; then - echo "The Preprocessed Data (.hkl ) exist" -else - python ../workflow_video_prediction/DataPreprocess/benchmark/mpi_stager_v2_process_netCDF.py \ - --input_dir ${DATA_EXTRA_DIR} --destination_dir ${DATA_PREPROCESS_DIR} -fi - -#Change the .hkl data to .tfrecords files -if [ -d "$DATA_PREPROCESS_TF_DIR" ] -then - echo "Step2: The Preprocessed Data (tf.records) exist" -else - echo "Step2: start, hkl. files to tf.records" - python ./video_prediction/datasets/era5_dataset_v2.py --source_dir ${DATA_PREPROCESS_DIR}/splits \ - --destination_dir ${DATA_PREPROCESS_TF_DIR} - echo "Step2: finish" -fi - -#########Train########################## -if [ "$TRAIN_MODE" == "pre_trained" ]; then - echo "step3: Using kth pre_trained model" -elif [ "$TRAIN_MODE" == "end_to_end" ]; then - echo "step3: End-to-end training" - if [ "$RETRAIN" == 1 ]; then - echo "Using the existing end-to-end model" - else - echo "Step3: Training Starts " - python ./scripts/train_v2.py --input_dir $DATA_PREPROCESS_TF_DIR --dataset era5 \ - --model ${MODEL} --model_hparams_dict hparams/kth/${method_dir}/model_hparams.json \ - --output_dir ${TRAIN_OUTPUT_DIR} --checkpoint ${CHECKPOINT_DIR_DIR} - echo "Training ends " - fi -else - echo "TRAIN_MODE is end_to_end or pre_trained" - exit 1 -fi - -#########Generate results################# -echo "Step4: Postprocessing start" -python ./scripts/generate_transfer_learning_finetune.py --input_dir ${DATA_PREPROCESS_TF_DIR} \ ---dataset_hparams sequence_length=20 --checkpoint ${CHECKPOINT_DIR_DIR} --mode test --results_dir ${RESULTS_OUTPUT_DIR} \ ---batch_size 4 --dataset era5 \ No newline at end of file diff --git a/video_prediction_savp/bash/workflow_era5_macOS.sh b/video_prediction_savp/bash/workflow_era5_macOS.sh deleted file mode 100755 index 1a6ebef3..00000000 --- a/video_prediction_savp/bash/workflow_era5_macOS.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env bash -set -e -# -#MODEL=savp -##train_mode: end_to_end, pre_trained -#TRAIN_MODE=end_to_end -#EXP_NAME=era5_size_64_64_3_3t_norm - -MODEL=$1 -TRAIN_MODE=$2 -EXP_NAME=$3 -RETRAIN=1 #if we continue training the model or using the existing end-to-end model, 1 means continue training, and 1 means use the existing one -DATA_ETL_DIR=/p/scratch/deepacf/${USER}/ -DATA_ETL_DIR=/p/scratch/deepacf/${USER}/ -DATA_EXTRA_DIR=${DATA_ETL_DIR}/extractedData/${EXP_NAME} -DATA_PREPROCESS_DIR=${DATA_ETL_DIR}/preprocessedData/${EXP_NAME} -DATA_PREPROCESS_TF_DIR=./data/${EXP_NAME} -RESULTS_OUTPUT_DIR=./results_test_samples/${EXP_NAME}/${TRAIN_MODE}/ - -if [ $MODEL==savp ]; then - method_dir=ours_savp -elif [ $MODEL==gan ]; then - method_dir=ours_gan -elif [ $MODEL==vae ]; then - method_dir=ours_vae -else - echo "model does not exist" 2>&1 - exit 1 -fi - -if [ "$TRAIN_MODE" == pre_trained ]; then - TRAIN_OUTPUT_DIR=./pretrained_models/kth/${method_dir} -else - TRAIN_OUTPUT_DIR=./logs/${EXP_NAME}/${TRAIN_MODE} -fi - -CHECKPOINT_DIR=${TRAIN_OUTPUT_DIR}/${method_dir} - -echo "===========================WORKFLOW SETUP====================" -echo "Model ${MODEL}" -echo "TRAIN MODE ${TRAIN_MODE}" -echo "Method_dir ${method_dir}" -echo "DATA_ETL_DIR ${DATA_ETL_DIR}" -echo "DATA_EXTRA_DIR ${DATA_EXTRA_DIR}" -echo "DATA_PREPROCESS_DIR ${DATA_PREPROCESS_DIR}" -echo "DATA_PREPROCESS_TF_DIR ${DATA_PREPROCESS_TF_DIR}" -echo "TRAIN_OUTPUT_DIR ${TRAIN_OUTPUT_DIR}" -echo "=============================================================" - -##############Datat Preprocessing################ -#To hkl data -#if [ -d "$DATA_PREPROCESS_DIR" ]; then -# echo "The Preprocessed Data (.hkl ) exist" -#else -# python ../workflow_video_prediction/DataPreprocess/benchmark/mpi_stager_v2_process_netCDF.py \ -# --input_dir ${DATA_EXTRA_DIR} --destination_dir ${DATA_PREPROCESS_DIR} -#fi - -####Change the .hkl data to .tfrecords files -if [ -d "$DATA_PREPROCESS_TF_DIR" ] -then - echo "Step2: The Preprocessed Data (tf.records) exist" -else - echo "Step2: start, hkl. files to tf.records" - python ./video_prediction/datasets/era5_dataset_v2.py --source_dir ${DATA_PREPROCESS_DIR}/splits \ - --destination_dir ${DATA_PREPROCESS_TF_DIR} - echo "Step2: finish" -fi - -#########Train########################## -if [ "$TRAIN_MODE" == "pre_trained" ]; then - echo "step3: Using kth pre_trained model" -elif [ "$TRAIN_MODE" == "end_to_end" ]; then - echo "step3: End-to-end training" - if [ "$RETRAIN" == 1 ]; then - echo "Using the existing end-to-end model" - else - echo "Training Starts " - python ./scripts/train_v2.py --input_dir $DATA_PREPROCESS_TF_DIR --dataset era5 \ - --model ${MODEL} --model_hparams_dict hparams/kth/${method_dir}/model_hparams.json \ - --output_dir ${TRAIN_OUTPUT_DIR} --checkpoint ${CHECKPOINT_DIR} - echo "Training ends " - fi -else - echo "TRAIN_MODE is end_to_end or pre_trained" - exit 1 -fi - -#########Generate results################# -echo "Step4: Postprocessing start" -python ./scripts/generate_transfer_learning_finetune.py --input_dir ${DATA_PREPROCESS_TF_DIR} \ ---dataset_hparams sequence_length=20 --checkpoint ${CHECKPOINT_DIR} --mode test --results_dir ${RESULTS_OUTPUT_DIR} \ ---batch_size 4 --dataset era5 diff --git a/video_prediction_savp/bash/workflow_era5_zam347.sh b/video_prediction_savp/bash/workflow_era5_zam347.sh deleted file mode 100755 index ffe7209b..00000000 --- a/video_prediction_savp/bash/workflow_era5_zam347.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env bash -set -e -# -#MODEL=savp -##train_mode: end_to_end, pre_trained -#TRAIN_MODE=end_to_end -#EXP_NAME=era5_size_64_64_3_3t_norm - -MODEL=$1 -TRAIN_MODE=$2 -EXP_NAME=$3 -RETRAIN=1 #if we continue training the model or using the existing end-to-end model, 1 means continue training, and 1 means use the existing one -DATA_ETL_DIR=/home/${USER}/ -DATA_ETL_DIR=/p/scratch/deepacf/${USER}/ -DATA_EXTRA_DIR=${DATA_ETL_DIR}/extractedData/${EXP_NAME} -DATA_PREPROCESS_DIR=${DATA_ETL_DIR}/preprocessedData/${EXP_NAME} -DATA_PREPROCESS_TF_DIR=./data/${EXP_NAME} -RESULTS_OUTPUT_DIR=./results_test_samples/${EXP_NAME}/${TRAIN_MODE}/ - -if [ $MODEL==savp ]; then - method_dir=ours_savp -elif [ $MODEL==gan ]; then - method_dir=ours_gan -elif [ $MODEL==vae ]; then - method_dir=ours_vae -else - echo "model does not exist" 2>&1 - exit 1 -fi - -if [ "$TRAIN_MODE" == pre_trained ]; then - TRAIN_OUTPUT_DIR=./pretrained_models/kth/${method_dir} -else - TRAIN_OUTPUT_DIR=./logs/${EXP_NAME}/${TRAIN_MODE} -fi - -CHECKPOINT_DIR=${TRAIN_OUTPUT_DIR}/${method_dir} - -echo "===========================WORKFLOW SETUP====================" -echo "Model ${MODEL}" -echo "TRAIN MODE ${TRAIN_MODE}" -echo "Method_dir ${method_dir}" -echo "DATA_ETL_DIR ${DATA_ETL_DIR}" -echo "DATA_EXTRA_DIR ${DATA_EXTRA_DIR}" -echo "DATA_PREPROCESS_DIR ${DATA_PREPROCESS_DIR}" -echo "DATA_PREPROCESS_TF_DIR ${DATA_PREPROCESS_TF_DIR}" -echo "TRAIN_OUTPUT_DIR ${TRAIN_OUTPUT_DIR}" -echo "=============================================================" - -##############Datat Preprocessing################ -#To hkl data -#if [ -d "$DATA_PREPROCESS_DIR" ]; then -# echo "The Preprocessed Data (.hkl ) exist" -#else -# python ../workflow_video_prediction/DataPreprocess/benchmark/mpi_stager_v2_process_netCDF.py \ -# --input_dir ${DATA_EXTRA_DIR} --destination_dir ${DATA_PREPROCESS_DIR} -#fi - -####Change the .hkl data to .tfrecords files -if [ -d "$DATA_PREPROCESS_TF_DIR" ] -then - echo "Step2: The Preprocessed Data (tf.records) exist" -else - echo "Step2: start, hkl. files to tf.records" - python ./video_prediction/datasets/era5_dataset_v2.py --source_dir ${DATA_PREPROCESS_DIR}/splits \ - --destination_dir ${DATA_PREPROCESS_TF_DIR} - echo "Step2: finish" -fi - -#########Train########################## -if [ "$TRAIN_MODE" == "pre_trained" ]; then - echo "step3: Using kth pre_trained model" -elif [ "$TRAIN_MODE" == "end_to_end" ]; then - echo "step3: End-to-end training" - if [ "$RETRAIN" == 1 ]; then - echo "Using the existing end-to-end model" - else - echo "Training Starts " - python ./scripts/train_v2.py --input_dir $DATA_PREPROCESS_TF_DIR --dataset era5 \ - --model ${MODEL} --model_hparams_dict hparams/kth/${method_dir}/model_hparams.json \ - --output_dir ${TRAIN_OUTPUT_DIR} --checkpoint ${CHECKPOINT_DIR} - echo "Training ends " - fi -else - echo "TRAIN_MODE is end_to_end or pre_trained" - exit 1 -fi - -#########Generate results################# -echo "Step4: Postprocessing start" -python ./scripts/generate_transfer_learning_finetune.py --input_dir ${DATA_PREPROCESS_TF_DIR} \ ---dataset_hparams sequence_length=20 --checkpoint ${CHECKPOINT_DIR} --mode test --results_dir ${RESULTS_OUTPUT_DIR} \ ---batch_size 4 --dataset era5 diff --git a/video_prediction_savp/helper/helper.py b/video_prediction_savp/deprecate/helper/helper.py similarity index 100% rename from video_prediction_savp/helper/helper.py rename to video_prediction_savp/deprecate/helper/helper.py diff --git a/video_prediction_savp/pretrained_models/download_model.sh b/video_prediction_savp/deprecate/pretrained_models/download_model.sh similarity index 100% rename from video_prediction_savp/pretrained_models/download_model.sh rename to video_prediction_savp/deprecate/pretrained_models/download_model.sh diff --git a/video_prediction_savp/scripts/combine_results.py b/video_prediction_savp/deprecate/scripts/combine_results.py similarity index 100% rename from video_prediction_savp/scripts/combine_results.py rename to video_prediction_savp/deprecate/scripts/combine_results.py diff --git a/video_prediction_savp/scripts/evaluate.py b/video_prediction_savp/deprecate/scripts/evaluate.py similarity index 100% rename from video_prediction_savp/scripts/evaluate.py rename to video_prediction_savp/deprecate/scripts/evaluate.py diff --git a/video_prediction_savp/scripts/evaluate_all.sh b/video_prediction_savp/deprecate/scripts/evaluate_all.sh similarity index 100% rename from video_prediction_savp/scripts/evaluate_all.sh rename to video_prediction_savp/deprecate/scripts/evaluate_all.sh diff --git a/video_prediction_savp/scripts/generate_all.sh b/video_prediction_savp/deprecate/scripts/generate_all.sh similarity index 100% rename from video_prediction_savp/scripts/generate_all.sh rename to video_prediction_savp/deprecate/scripts/generate_all.sh diff --git a/video_prediction_savp/scripts/generate_orig.py b/video_prediction_savp/deprecate/scripts/generate_orig.py similarity index 100% rename from video_prediction_savp/scripts/generate_orig.py rename to video_prediction_savp/deprecate/scripts/generate_orig.py diff --git a/video_prediction_savp/scripts/plot_results.py b/video_prediction_savp/deprecate/scripts/plot_results.py similarity index 100% rename from video_prediction_savp/scripts/plot_results.py rename to video_prediction_savp/deprecate/scripts/plot_results.py diff --git a/video_prediction_savp/scripts/plot_results_all.sh b/video_prediction_savp/deprecate/scripts/plot_results_all.sh similarity index 100% rename from video_prediction_savp/scripts/plot_results_all.sh rename to video_prediction_savp/deprecate/scripts/plot_results_all.sh diff --git a/video_prediction_savp/scripts/train.py b/video_prediction_savp/deprecate/scripts/train.py similarity index 100% rename from video_prediction_savp/scripts/train.py rename to video_prediction_savp/deprecate/scripts/train.py diff --git a/video_prediction_savp/scripts/train_all.sh b/video_prediction_savp/deprecate/scripts/train_all.sh similarity index 100% rename from video_prediction_savp/scripts/train_all.sh rename to video_prediction_savp/deprecate/scripts/train_all.sh diff --git a/video_prediction_savp/docs/presentation/presentation.md b/video_prediction_savp/docs/presentation/presentation.md deleted file mode 100644 index d4923908..00000000 --- a/video_prediction_savp/docs/presentation/presentation.md +++ /dev/null @@ -1,5 +0,0 @@ -This is the presentation materials for VP group - - -## 2020-03-01 - 2020-03-31 -https://docs.google.com/presentation/d/18EJKBJJ2LHI7uNU_l8s_Cm-aGZhw9tkoQ8BxqYZfkWk/edit#slide=id.g71f805bc32_0_80 diff --git a/video_prediction_savp/scripts/Analysis_all.py b/video_prediction_savp/scripts/Analysis_all.py deleted file mode 100644 index 7ed4b6b6..00000000 --- a/video_prediction_savp/scripts/Analysis_all.py +++ /dev/null @@ -1,105 +0,0 @@ -import pickle -import os -from matplotlib.pylab import plt - -# results_path = ["results_test_samples/era5_size_64_64_3_norm_dup_pretrained/ours_savp","results_test_samples/era5_size_64_64_3_norm_dup_pretrained_finetune/ours_savp", -# "results_test_samples/era5_size_64_64_3_norm_dup_pretrained_gan/kth_ours_gan","results_test_samples/era5_size_64_64_3_norm_dup_pretrained_vae_l1/kth_ours_vae_l1"] -# -# model_names = ["SAVP","SAVP_Finetune","GAN","VAE"] - - -# results_path = ["results_test_samples/era5_size_64_64_3_norm_dup_pretrained/ours_savp","results_test_samples/era5_size_64_64_3_norm_msl_gph_pretrained_savp/ours_savp", -# "results_test_samples/era5_size_64_64_3_norm_dup_pretrained_gan/kth_ours_gan","results_test_samples/era5_size_64_64_3_norm_msl_gph_pretrained_gan/kth_ours_gan"] -# -# model_names = ["SAVP_3T","SAVP_T-MSL-GPH","GAN_3T","GAN_T-MSL_GPH"] -# -# results_path = ["results_test_samples/era5_size_64_64_3_norm_dup_pretrained/ours_savp","results_test_samples/era5_size_64_64_3_norm_dup/ours_savp", -# "results_test_samples/era5_size_64_64_3_norm_dup_pretrained/kth_ours_gan","results_test_samples/era5_size_64_64_3_norm_dup/ours_gan", -# "results_test_samples/era5_size_64_64_3_norm_dup_pretrained/kth_ours_vae_l1","results_test_samples/era5_size_64_64_3_norm_dup/ours_vae_l1"] -# model_names = ["TF-SAVP(KTH)","SAVP (3T)","TF-GAN(KTH)","GAN (3T)","TF-VAE (KTH)","VAE (3T)"] - -## -##results_path = ["results_test_samples/era5_size_64_64_3_norm_t_msl_gph/ours_savp", "results_test_samples/era5_size_64_64_3_norm_dup/ours_savp", -## "results_test_samples/era5_size_64_64_3_norm_t_msl_gph/ours_gan","results_test_samples/era5_size_64_64_3_norm_dup/ours_gan"] -##model_names = ["SAVP(T-MSL-GPH)", "SAVP (3T)", "GAN (T-MSL-GPH)","GAN (3T)"] - -##results_path = ["results_test_samples/era5_size_64_64_3_norm_t_msl_gph/ours_savp", "results_test_samples/era5_size_64_64_3_norm_dup/ours_savp", -## "results_test_samples/era5_size_64_64_3_norm_t_msl_gph/ours_gan","results_test_samples/era5_size_64_64_3_norm_dup/ours_gan"] -##model_names = ["SAVP(T-MSL-GPH)", "SAVP (3T)", "GAN (T-MSL-GPH)","GAN (3T)"] -## -##mse_all = [] -##psnr_all = [] -##ssim_all = [] -##for path in results_path: -## p = os.path.join(path,"results.pkl") -## result = pickle.load(open(p,"rb")) -## mse = result["mse"] -## psnr = result["psnr"] -## ssim = result["ssim"] -## mse_all.append(mse) -## psnr_all.append(psnr) -## ssim_all.append(ssim) -## -## -##def get_metric(metrtic): -## if metric == "mse": -## return mse_all -## elif metric == "psnr": -## return psnr_all -## elif metric == "ssim": -## return ssim_all -## else: -## raise("Metric error") -## -##for metric in ["mse","psnr","ssim"]: -## evals = get_metric(metric) -## timestamp = list(range(1,11)) -## fig = plt.figure() -## plt.plot(timestamp, evals[0],'-.',label=model_names[0]) -## plt.plot(timestamp, evals[1],'--',label=model_names[1]) -## plt.plot(timestamp, evals[2],'-',label=model_names[2]) -## plt.plot(timestamp, evals[3],'--.',label=model_names[3]) -## # plt.plot(timestamp, evals[4],'*-.',label=model_names[4]) -## # plt.plot(timestamp, evals[5],'--*',label=model_names[5]) -## if metric == "mse": -## plt.legend(loc="upper left") -## else: -## plt.legend(loc = "upper right") -## plt.xlabel("Timestamps") -## plt.ylabel(metric) -## plt.title(metric,fontsize=15) -## plt.savefig(metric + "2.png") -## plt.clf() - - - -#persistent analysis -persistent_mse_all = [] -persistent_psnr_all = [] -persistent_ssim_all = [] -mse_all = [] -psnr_all = [] -ssim_all = [] -results_root_path = "/p/scratch/deepacf/video_prediction_shared_folder/results/era5-Y2017M01to12-64x64-50d00N11d50E-T_T_T/ours_gan" -p1 = os.path.join(results_root_path,"results.pkl") -result1 = pickle.load(open(p1,"rb")) -p2 = os.path.join(results_root_path,"persistent_results.pkl") -result2 = pickle.load(open(p2,"rb")) -mse = result1["mse"] -psnr = result1["psnr"] -ssim = result1["ssim"] -mse_all.append(mse) -psnr_all.append(psnr) -ssim_all.append(ssim) - -persistent_mse = result2["mse"] -persistent_psnr = result2["psnr"] -persistent_ssim = result2["ssim"] -persistent_mse_all.append(persistent_mse) -persistent_psnr_all.append(persistent_psnr) -persistent_ssim_all.append(persistent_ssim) - - - -print("persistent_mse",persistent_mse_all) -print("mse",mse_all) diff --git a/video_prediction_savp/scripts/evaluate_svg.sh b/video_prediction_savp/scripts/evaluate_svg.sh deleted file mode 100644 index 212c4ba2..00000000 --- a/video_prediction_savp/scripts/evaluate_svg.sh +++ /dev/null @@ -1 +0,0 @@ -#!/usr/bin/env bash \ No newline at end of file diff --git a/video_prediction_savp/scripts/generate.py b/video_prediction_savp/scripts/generate.py deleted file mode 100644 index e1893194..00000000 --- a/video_prediction_savp/scripts/generate.py +++ /dev/null @@ -1,537 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import argparse -import errno -import json -import os -import math -import random -import cv2 -import numpy as np -import tensorflow as tf -import seaborn as sns -import pickle -from random import seed -import random -import json -import numpy as np -#from six.moves import cPickle -import matplotlib -matplotlib.use('Agg') -import matplotlib.pyplot as plt -import matplotlib.gridspec as gridspec -import matplotlib.animation as animation -import seaborn as sns -import pandas as pd -from video_prediction import datasets, models -from matplotlib.colors import LinearSegmentedColormap -from matplotlib.ticker import MaxNLocator -from video_prediction.utils.ffmpeg_gif import save_gif - -with open("./splits_size_64_64_1/geo_info.json","r") as json_file: - geo = json.load(json_file) - lat = [round(i,2) for i in geo["lat"]] - lon = [round(i,2) for i in geo["lon"]] - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument("--input_dir", type=str, required=True, help="either a directory containing subdirectories " - "train, val, test, etc, or a directory containing " - "the tfrecords") - parser.add_argument("--results_dir", type=str, default='results', help="ignored if output_gif_dir is specified") - parser.add_argument("--results_gif_dir", type=str, help="default is results_dir. ignored if output_gif_dir is specified") - parser.add_argument("--results_png_dir", type=str, help="default is results_dir. ignored if output_png_dir is specified") - parser.add_argument("--output_gif_dir", help="output directory where samples are saved as gifs. default is " - "results_gif_dir/model_fname") - parser.add_argument("--output_png_dir", help="output directory where samples are saved as pngs. default is " - "results_png_dir/model_fname") - parser.add_argument("--checkpoint", help="directory with checkpoint or checkpoint name (e.g. checkpoint_dir/model-200000)") - - parser.add_argument("--mode", type=str, choices=['val', 'test'], default='val', help='mode for dataset, val or test.') - - parser.add_argument("--dataset", type=str, help="dataset class name") - parser.add_argument("--dataset_hparams", type=str, help="a string of comma separated list of dataset hyperparameters") - parser.add_argument("--model", type=str, help="model class name") - parser.add_argument("--model_hparams", type=str, help="a string of comma separated list of model hyperparameters") - - parser.add_argument("--batch_size", type=int, default=8, help="number of samples in batch") - parser.add_argument("--num_samples", type=int, help="number of samples in total (all of them by default)") - parser.add_argument("--num_epochs", type=int, default=1) - - parser.add_argument("--num_stochastic_samples", type=int, default=1) #Bing original is 5, change to 1 - parser.add_argument("--gif_length", type=int, help="default is sequence_length") - parser.add_argument("--fps", type=int, default=4) - - parser.add_argument("--gpu_mem_frac", type=float, default=0, help="fraction of gpu memory to use") - parser.add_argument("--seed", type=int, default=7) - - args = parser.parse_args() - - if args.seed is not None: - tf.set_random_seed(args.seed) - np.random.seed(args.seed) - random.seed(args.seed) - - args.results_gif_dir = args.results_gif_dir or args.results_dir - args.results_png_dir = args.results_png_dir or args.results_dir - dataset_hparams_dict = {} - model_hparams_dict = {} - if args.checkpoint: - checkpoint_dir = os.path.normpath(args.checkpoint) - if not os.path.isdir(args.checkpoint): - checkpoint_dir, _ = os.path.split(checkpoint_dir) - if not os.path.exists(checkpoint_dir): - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), checkpoint_dir) - with open(os.path.join(checkpoint_dir, "options.json")) as f: - print("loading options from checkpoint %s" % args.checkpoint) - options = json.loads(f.read()) - args.dataset = args.dataset or options['dataset'] - args.model = args.model or options['model'] - try: - with open(os.path.join(checkpoint_dir, "dataset_hparams.json")) as f: - dataset_hparams_dict = json.loads(f.read()) - except FileNotFoundError: - print("dataset_hparams.json was not loaded because it does not exist") - try: - with open(os.path.join(checkpoint_dir, "model_hparams.json")) as f: - model_hparams_dict = json.loads(f.read()) - except FileNotFoundError: - print("model_hparams.json was not loaded because it does not exist") - args.output_gif_dir = args.output_gif_dir or os.path.join(args.results_gif_dir, os.path.split(checkpoint_dir)[1]) - args.output_png_dir = args.output_png_dir or os.path.join(args.results_png_dir, os.path.split(checkpoint_dir)[1]) - else: - if not args.dataset: - raise ValueError('dataset is required when checkpoint is not specified') - if not args.model: - raise ValueError('model is required when checkpoint is not specified') - args.output_gif_dir = args.output_gif_dir or os.path.join(args.results_gif_dir, 'model.%s' % args.model) - args.output_png_dir = args.output_png_dir or os.path.join(args.results_png_dir, 'model.%s' % args.model) - - print('----------------------------------- Options ------------------------------------') - for k, v in args._get_kwargs(): - print(k, "=", v) - print('------------------------------------- End --------------------------------------') - - VideoDataset = datasets.get_dataset_class(args.dataset) - dataset = VideoDataset( - args.input_dir, - mode=args.mode, - num_epochs=args.num_epochs, - seed=args.seed, - hparams_dict=dataset_hparams_dict, - hparams=args.dataset_hparams) - VideoPredictionModel = models.get_model_class(args.model) - hparams_dict = dict(model_hparams_dict) - hparams_dict.update({ - 'context_frames': dataset.hparams.context_frames, - 'sequence_length': dataset.hparams.sequence_length, - 'repeat': dataset.hparams.time_shift, - }) - model = VideoPredictionModel( - mode=args.mode, - hparams_dict=hparams_dict, - hparams=args.model_hparams) - - sequence_length = model.hparams.sequence_length - context_frames = model.hparams.context_frames - future_length = sequence_length - context_frames - - if args.num_samples: - if args.num_samples > dataset.num_examples_per_epoch(): - raise ValueError('num_samples cannot be larger than the dataset') - num_examples_per_epoch = args.num_samples - else: - #Bing: error occurs here, cheats a little bit here - #num_examples_per_epoch = dataset.num_examples_per_epoch() - num_examples_per_epoch = args.batch_size * 8 - if num_examples_per_epoch % args.batch_size != 0: - #bing - #raise ValueError('batch_size should evenly divide the dataset size %d' % num_examples_per_epoch) - pass - #Bing if it is era 5 data we used dataset.make_batch_v2 - #inputs = dataset.make_batch(args.batch_size) - inputs = dataset.make_batch(args.batch_size) - input_phs = {k: tf.placeholder(v.dtype, v.shape, '%s_ph' % k) for k, v in inputs.items()} - with tf.variable_scope(''): - model.build_graph(input_phs) - - for output_dir in (args.output_gif_dir, args.output_png_dir): - if not os.path.exists(output_dir): - os.makedirs(output_dir) - with open(os.path.join(output_dir, "options.json"), "w") as f: - f.write(json.dumps(vars(args), sort_keys=True, indent=4)) - with open(os.path.join(output_dir, "dataset_hparams.json"), "w") as f: - f.write(json.dumps(dataset.hparams.values(), sort_keys=True, indent=4)) - with open(os.path.join(output_dir, "model_hparams.json"), "w") as f: - f.write(json.dumps(model.hparams.values(), sort_keys=True, indent=4)) - - gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_mem_frac) - config = tf.ConfigProto(gpu_options=gpu_options, allow_soft_placement=True) - sess = tf.Session(config=config) - sess.graph.as_default() - model.restore(sess, args.checkpoint) - sample_ind = 0 - gen_images_all = [] - input_images_all = [] - - while True: - if args.num_samples and sample_ind >= args.num_samples: - break - try: - input_results = sess.run(inputs) - except tf.errors.OutOfRangeError: - break - print("evaluation samples from %d to %d" % (sample_ind, sample_ind + args.batch_size)) - feed_dict = {input_ph: input_results[name] for name, input_ph in input_phs.items()} - for stochastic_sample_ind in range(args.num_stochastic_samples): #Todo: why use here - print("Stochastic sample id", stochastic_sample_ind) - gen_images = sess.run(model.outputs['gen_images'], feed_dict=feed_dict) - #input_images = sess.run(inputs["images"]) - #Bing: Add evaluation metrics - # fetches = {'images': model.inputs['images']} - # fetches.update(model.eval_outputs.items()) - # fetches.update(model.eval_metrics.items()) - # results = sess.run(fetches, feed_dict = feed_dict) - # input_images = results["images"] #shape (batch_size,future_frames,height,width,channel) - # only keep the future frames - #gen_images = gen_images[:, -future_length:] #(8,10,64,64,1) (batch_size, sequences, height, width, channel) - #input_images = input_results["images"][:,-future_length:,:,:] - input_images = input_results["images"][:,1:,:,:,:] - #gen_mse_avg = results["eval_mse/avg"] #shape (batch_size,future_frames) - print("Finish sample ind",stochastic_sample_ind) - input_gen_diff_ = input_images - gen_images - #diff_image_range = pd.cut(input_gen_diff_.flatten(), bins = 4, labels = [-10, -5, 0, 5], right = False) - #diff_image_range = np.reshape(np.array(diff_image_range),input_gen_diff_.shape) - gen_images_all.extend(gen_images) - input_images_all.extend(input_images) - - colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] - cmap_name = 'my_list' - if sample_ind < 100: - for i in range(len(gen_images)): - name = 'Batch_id_' + str(sample_ind) + " + Sample_" + str(i) - gen_images_ = gen_images[i, :] - gen_mse_avg_ = [np.mean(input_gen_diff_[i, frame, :, :, :]**2) for frame in - range(19)] # return the list with 10 (sequence) mse - input_gen_diff = input_gen_diff_ [i,:,:,:,:] - input_images_ = input_images[i, :] - #gen_mse_avg_ = gen_mse_avg[i, :] - - # Bing: This is to check the difference between the images and next images for debugging the freezon issues - # gen_images_diff = [] - # for gen_idx in range(len(gen_images_) - 1): - # img_1 = gen_images_[gen_idx, :, :, :] - # img_2 = gen_images_[gen_idx + 1, :, :, :] - # img_diff = img_2 - img_1 - # img_diff_nonzero = [e for img_idx, e in enumerate(img_diff.flatten()) if round(e,3) != 0.000] - # gen_images_diff.append(img_diff_nonzero) - - fig = plt.figure() - gs = gridspec.GridSpec(4,6) - gs.update(wspace = 0.7,hspace=0.8) - ax1 = plt.subplot(gs[0:2,0:3]) - ax2 = plt.subplot(gs[0:2,3:],sharey=ax1) - ax3 = plt.subplot(gs[2:4,0:3]) - ax4 = plt.subplot(gs[2:4,3:]) - xlables = [round(i,2) for i in list(np.linspace(np.min(lon),np.max(lon),5))] - ylabels = [round(i,2) for i in list(np.linspace(np.max(lat),np.min(lat),5))] - plt.setp([ax1,ax2,ax3],xticks=list(np.linspace(0,64,5)), xticklabels=xlables ,yticks=list(np.linspace(0,64,5)),yticklabels=ylabels) - ax1.title.set_text("(a) Ground Truth") - ax2.title.set_text("(b) SAVP") - ax3.title.set_text("(c) Diff.") - ax4.title.set_text("(d) MSE") - - ax1.xaxis.set_tick_params(labelsize=7) - ax1.yaxis.set_tick_params(labelsize = 7) - ax2.xaxis.set_tick_params(labelsize=7) - ax2.yaxis.set_tick_params(labelsize = 7) - ax3.xaxis.set_tick_params(labelsize=7) - ax3.yaxis.set_tick_params(labelsize = 7) - - init_images = np.zeros((input_images_.shape[1], input_images_.shape[2])) - print("inti images shape", init_images.shape) - xdata, ydata = [], [] - plot1 = ax1.imshow(init_images, cmap='jet', vmin = 270, vmax = 300) - plot2 = ax2.imshow(init_images, cmap='jet', vmin = 270, vmax = 300) - #x = np.linspace(0, 64, 64) - #y = np.linspace(0, 64, 64) - #plot1 = ax1.contourf(x,y,init_images, cmap='jet', vmin = np.min(input_images), vmax = np.max(input_images)) - #plot2 = ax2.contourf(x,y,init_images, cmap='jet', vmin = np.min(input_images), vmax = np.max(input_images)) - fig.colorbar(plot1, ax=ax1).ax.tick_params(labelsize=7) - fig.colorbar(plot2, ax=ax2).ax.tick_params(labelsize=7) - - cm = LinearSegmentedColormap.from_list( - cmap_name, "bwr", N = 5) - - plot3 = ax3.imshow(init_images, vmin=-10, vmax=10, cmap=cm)#cmap = 'PuBu_r', - plot4, = ax4.plot([], [], color = "r") - ax4.set_xlim(0, len(gen_mse_avg_)-1) - ax4.set_ylim(0, 10) - ax4.set_xlabel("Frames", fontsize=10) - #ax4.set_ylabel("MSE", fontsize=10) - ax4.xaxis.set_tick_params(labelsize=7) - ax4.yaxis.set_tick_params(labelsize=7) - - - plots = [plot1, plot2, plot3, plot4] - - #fig.colorbar(plots[1], ax = [ax1, ax2]) - - fig.colorbar(plots[2], ax=ax3).ax.tick_params(labelsize=7) - #fig.colorbar(plot1[0], ax=ax1).ax.tick_params(labelsize=7) - #fig.colorbar(plot2[1], ax=ax2).ax.tick_params(labelsize=7) - - def animation_sample(t): - input_image = input_images_[t, :, :, 0] - gen_image = gen_images_[t, :, :, 0] - diff_image = input_gen_diff[t,:,:,0] - - data = gen_mse_avg_[:t + 1] - # x = list(range(len(gen_mse_avg_)))[:t+1] - xdata.append(t) - print("xdata", xdata) - ydata.append(gen_mse_avg_[t]) - - print("ydata", ydata) - # p = sns.lineplot(x=x,y=data,color="b") - # p.tick_params(labelsize=17) - # plt.setp(p.lines, linewidth=6) - plots[0].set_data(input_image) - plots[1].set_data(gen_image) - #plots[0] = ax1.contourf(x, y, input_image, cmap = 'jet', vmin = np.min(input_images),vmax = np.max(input_images)) - #plots[1] = ax2.contourf(x, y, gen_image, cmap = 'jet', vmin = np.min(input_images),vmax = np.max(input_images)) - plots[2].set_data(diff_image) - plots[3].set_data(xdata, ydata) - fig.suptitle("Frame " + str(t+1)) - - return plots - - ani = animation.FuncAnimation(fig, animation_sample, frames=len(gen_mse_avg_), interval = 1000, - repeat_delay = 2000) - ani.save(os.path.join(args.output_png_dir, "Sample_" + str(name) + ".mp4")) - - else: - pass - - - - - - - - - - - - - - - - - - # # for i, gen_mse_avg_ in enumerate(gen_mse_avg): - # # ims = [] - # # fig = plt.figure() - # # plt.xlim(0,len(gen_mse_avg_)) - # # plt.ylim(np.min(gen_mse_avg),np.max(gen_mse_avg)) - # # plt.xlabel("Frames") - # # plt.ylabel("MSE_AVG") - # # #X = list(range(len(gen_mse_avg_))) - # # #for t, gen_mse_avg_ in enumerate(gen_mse_avg): - # # def animate_metric(j): - # # data = gen_mse_avg_[:(j+1)] - # # x = list(range(len(gen_mse_avg_)))[:(j+1)] - # # p = sns.lineplot(x=x,y=data,color="b") - # # p.tick_params(labelsize=17) - # # plt.setp(p.lines, linewidth=6) - # # ani = animation.FuncAnimation(fig, animate_metric, frames=len(gen_mse_avg_), interval = 1000, repeat_delay=2000) - # # ani.save(os.path.join(args.output_png_dir, "MSE_AVG" + str(i) + ".gif")) - # # - # # - # # for i, input_images_ in enumerate(input_images): - # # #context_images_ = (input_results['images'][i]) - # # #gen_images_fname = 'gen_image_%05d_%02d.gif' % (sample_ind + i, stochastic_sample_ind) - # # ims = [] - # # fig = plt.figure() - # # for t, input_image in enumerate(input_images_): - # # im = plt.imshow(input_images[i, t, :, :, 0], interpolation = 'none') - # # ttl = plt.text(1.5, 2,"Frame_" + str(t)) - # # ims.append([im,ttl]) - # # ani = animation.ArtistAnimation(fig, ims, interval= 1000, blit=True,repeat_delay=2000) - # # ani.save(os.path.join(args.output_png_dir,"groud_true_images_" + str(i) + ".gif")) - # # #plt.show() - # # - # # for i,gen_images_ in enumerate(gen_images): - # # ims = [] - # # fig = plt.figure() - # # for t, gen_image in enumerate(gen_images_): - # # im = plt.imshow(gen_images[i, t, :, :, 0], interpolation = 'none') - # # ttl = plt.text(1.5, 2, "Frame_" + str(t)) - # # ims.append([im, ttl]) - # # ani = animation.ArtistAnimation(fig, ims, interval = 1000, blit = True, repeat_delay = 2000) - # # ani.save(os.path.join(args.output_png_dir, "prediction_images_" + str(i) + ".gif")) - # - # - # # for i, gen_images_ in enumerate(gen_images): - # # #context_images_ = (input_results['images'][i] * 255.0).astype(np.uint8) - # # #gen_images_ = (gen_images_ * 255.0).astype(np.uint8) - # # #bing - # # context_images_ = (input_results['images'][i]) - # # gen_images_fname = 'gen_image_%05d_%02d.gif' % (sample_ind + i, stochastic_sample_ind) - # # context_and_gen_images = list(context_images_[:context_frames]) + list(gen_images_) - # # plt.figure(figsize = (10,2)) - # # gs = gridspec.GridSpec(2,10) - # # gs.update(wspace=0.,hspace=0.) - # # for t, gen_image in enumerate(gen_images_): - # # gen_image_fname_pattern = 'gen_image_%%05d_%%02d_%%0%dd.png' % max(2,len(str(len(gen_images_) - 1))) - # # gen_image_fname = gen_image_fname_pattern % (sample_ind + i, stochastic_sample_ind, t) - # # plt.subplot(gs[t]) - # # plt.imshow(input_images[i, t, :, :, 0], interpolation = 'none') # the last index sets the channel. 0 = t2 - # # # plt.pcolormesh(X_test[i,t,::-1,:,0], shading='bottom', cmap=plt.cm.jet) - # # plt.tick_params(axis = 'both', which = 'both', bottom = False, top = False, left = False, - # # right = False, labelbottom = False, labelleft = False) - # # if t == 0: plt.ylabel('Actual', fontsize = 10) - # # - # # plt.subplot(gs[t + 10]) - # # plt.imshow(gen_images[i, t, :, :, 0], interpolation = 'none') - # # # plt.pcolormesh(X_hat[i,t,::-1,:,0], shading='bottom', cmap=plt.cm.jet) - # # plt.tick_params(axis = 'both', which = 'both', bottom = False, top = False, left = False, - # # right = False, labelbottom = False, labelleft = False) - # # if t == 0: plt.ylabel('Predicted', fontsize = 10) - # # plt.savefig(os.path.join(args.output_png_dir, gen_image_fname) + 'plot_' + str(i) + '.png') - # # plt.clf() - # - # # if args.gif_length: - # # context_and_gen_images = context_and_gen_images[:args.gif_length] - # # save_gif(os.path.join(args.output_gif_dir, gen_images_fname), - # # context_and_gen_images, fps=args.fps) - # # - # # gen_image_fname_pattern = 'gen_image_%%05d_%%02d_%%0%dd.png' % max(2, len(str(len(gen_images_) - 1))) - # # for t, gen_image in enumerate(gen_images_): - # # gen_image_fname = gen_image_fname_pattern % (sample_ind + i, stochastic_sample_ind, t) - # # if gen_image.shape[-1] == 1: - # # gen_image = np.tile(gen_image, (1, 1, 3)) - # # else: - # # gen_image = cv2.cvtColor(gen_image, cv2.COLOR_RGB2BGR) - # # cv2.imwrite(os.path.join(args.output_png_dir, gen_image_fname), gen_image) - - sample_ind += args.batch_size - - - with open(os.path.join(args.output_png_dir, "input_images_all"),"wb") as input_files: - pickle.dump(input_images_all,input_files) - - with open(os.path.join(args.output_png_dir, "gen_images_all"),"wb") as gen_files: - pickle.dump(gen_images_all,gen_files) - - with open(os.path.join(args.output_png_dir, "input_images_all"),"rb") as input_files: - input_images_all = pickle.load(input_files) - - with open(os.path.join(args.output_png_dir, "gen_images_all"),"rb") as gen_files: - gen_images_all=pickle.load(gen_files) - ims = [] - fig = plt.figure() - for frame in range(19): - input_gen_diff = np.mean((np.array(gen_images_all) - np.array(input_images_all))**2, axis = 0)[frame, :,:, 0] # Get the first prediction frame (batch,height, width, channel) - #pix_mean = np.mean(input_gen_diff, axis = 0) - #pix_std = np.std(input_gen_diff, axis=0) - im = plt.imshow(input_gen_diff, interpolation = 'none',cmap='PuBu') - if frame == 0: - fig.colorbar(im) - ttl = plt.text(1.5, 2, "Frame_" + str(frame +1)) - ims.append([im, ttl]) - ani = animation.ArtistAnimation(fig, ims, interval = 1000, blit = True, repeat_delay = 2000) - ani.save(os.path.join(args.output_png_dir, "Mean_Frames.mp4")) - plt.close("all") - - ims = [] - fig = plt.figure() - for frame in range(19): - pix_std= np.std((np.array(gen_images_all) - np.array(input_images_all))**2, axis = 0)[frame, :,:, 0] # Get the first prediction frame (batch,height, width, channel) - #pix_mean = np.mean(input_gen_diff, axis = 0) - #pix_std = np.std(input_gen_diff, axis=0) - im = plt.imshow(pix_std, interpolation = 'none',cmap='PuBu') - if frame == 0: - fig.colorbar(im) - ttl = plt.text(1.5, 2, "Frame_" + str(frame+1)) - ims.append([im, ttl]) - ani = animation.ArtistAnimation(fig, ims, interval = 1000, blit = True, repeat_delay = 2000) - ani.save(os.path.join(args.output_png_dir, "Std_Frames.mp4")) - - gen_images_all = np.array(gen_images_all) - input_images_all = np.array(input_images_all) - # mse_model = np.mean((input_images_all[:, 1:,:,:,0] - gen_images_all[:, 1:,:,:,0])**2) # look at all timesteps except the first - # mse_model_last = np.mean((input_images_all[:, future_length-1,:,:,0] - gen_images_all[:, future_length-1,:,:,0])**2) - # mse_prev = np.mean((input_images_all[:, :-1,:,:,0] - gen_images_all[:, 1:,:,:,0])**2 ) - - mse_model = np.mean((input_images_all[:, :10,:,:,0] - gen_images_all[:, :10,:,:,0])**2) # look at all timesteps except the first - mse_model_last = np.mean((input_images_all[:,10,:,:,0] - gen_images_all[:, 10,:,:,0])**2) - mse_prev = np.mean((input_images_all[:, :9, :, :, 0] - input_images_all[:, 1:10, :, :, 0])**2 ) - - def psnr(img1, img2): - mse = np.mean((img1 - img2) ** 2) - if mse == 0: return 100 - PIXEL_MAX = 1 - return 20 * math.log10(PIXEL_MAX / math.sqrt(mse)) - - psnr_model = psnr(input_images_all[:, :10, :, :, 0], gen_images_all[:, :10, :, :, 0]) - psnr_model_last = psnr(input_images_all[:, 10, :, :, 0], gen_images_all[:,10, :, :, 0]) - psnr_prev = psnr(input_images_all[:, :9, :, :, 0], input_images_all[:, 1:10, :, :, 0]) - f = open(os.path.join(args.output_png_dir,'prediction_scores_4prediction.txt'), 'w') - f.write("Model MSE: %f\n" % mse_model) - f.write("Model MSE from only last prediction in sequence: %f\n" % mse_model_last) - f.write("Previous Frame MSE: %f\n" % mse_prev) - f.write("Model PSNR: %f\n" % psnr_model) - f.write("Model PSNR from only last prediction in sequence: %f\n" % psnr_model_last) - f.write("Previous frame PSNR: %f\n" % psnr_prev) - f.write("Shape of X_test: " + str(input_images_all.shape)) - f.write("") - f.write("Shape of X_hat: " + str(gen_images_all.shape)) - f.close() - - seed(1) - s = random.sample(range(len(gen_images_all)), 100) - print("******KDP******") - #kernel density plot for checking the model collapse - fig = plt.figure() - kdp = sns.kdeplot(gen_images_all[s].flatten(), shade=True, color="r", label = "Generate Images") - kdp = sns.kdeplot(input_images_all[s].flatten(), shade=True, color="b", label = "Ground True") - kdp.set(xlabel = 'Temperature (K)', ylabel = 'Probability') - plt.savefig(os.path.join(args.output_png_dir, "kdp_gen_images.png"), dpi = 400) - plt.clf() - - #line plot for evaluating the prediction and groud-truth - for i in [0,3,6,9,12,15,18]: - fig = plt.figure() - plt.scatter(gen_images_all[:,i,:,:][s].flatten(),input_images_all[:,i,:,:][s].flatten(),s=0.3) - #plt.scatter(gen_images_all[:,0,:,:].flatten(),input_images_all[:,0,:,:].flatten(),s=0.3) - plt.xlabel("Prediction") - plt.ylabel("Real values") - plt.title("Frame_{}".format(i+1)) - plt.plot([250,300], [250,300],color="black") - plt.savefig(os.path.join(args.output_png_dir,"pred_real_frame_{}.png".format(str(i)))) - plt.clf() - - - mse_model_by_frames = np.mean((input_images_all[:, :, :, :, 0][s] - gen_images_all[:, :, :, :, 0][s]) ** 2,axis=(2,3)) #return (batch, sequence) - x = [str(i+1) for i in list(range(19))] - fig,axis = plt.subplots() - mean_f = np.mean(mse_model_by_frames, axis = 0) - median = np.median(mse_model_by_frames, axis=0) - q_low = np.quantile(mse_model_by_frames, q=0.25, axis=0) - q_high = np.quantile(mse_model_by_frames, q=0.75, axis=0) - d_low = np.quantile(mse_model_by_frames,q=0.1, axis=0) - d_high = np.quantile(mse_model_by_frames, q=0.9, axis=0) - plt.fill_between(x, d_high, d_low, color="ghostwhite",label="interdecile range") - plt.fill_between(x,q_high, q_low , color = "lightgray", label="interquartile range") - plt.plot(x, median, color="grey", linewidth=0.6, label="Median") - plt.plot(x, mean_f, color="peachpuff",linewidth=1.5, label="Mean") - plt.title(f'MSE percentile') - plt.xlabel("Frames") - plt.legend(loc=2, fontsize=8) - plt.savefig(os.path.join(args.output_png_dir,"mse_percentiles.png")) - -if __name__ == '__main__': - main() diff --git a/workflow_parallel_frame_prediction/DataExtraction/mpi_stager_v2.py b/video_prediction_savp/scripts/mpi_stager_v2.py similarity index 100% rename from workflow_parallel_frame_prediction/DataExtraction/mpi_stager_v2.py rename to video_prediction_savp/scripts/mpi_stager_v2.py diff --git a/workflow_parallel_frame_prediction/DataPreprocess/mpi_stager_v2_process_netCDF.py b/video_prediction_savp/scripts/mpi_stager_v2_process_netCDF.py similarity index 100% rename from workflow_parallel_frame_prediction/DataPreprocess/mpi_stager_v2_process_netCDF.py rename to video_prediction_savp/scripts/mpi_stager_v2_process_netCDF.py diff --git a/video_prediction_savp/scripts/train_v2.py b/video_prediction_savp/scripts/train_v2.py deleted file mode 100644 index f83192d6..00000000 --- a/video_prediction_savp/scripts/train_v2.py +++ /dev/null @@ -1,362 +0,0 @@ -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import argparse -import errno -import json -import os -import random -import time - -import numpy as np -import tensorflow as tf - -from video_prediction import datasets, models - - -def add_tag_suffix(summary, tag_suffix): - summary_proto = tf.Summary() - summary_proto.ParseFromString(summary) - summary = summary_proto - - for value in summary.value: - tag_split = value.tag.split('/') - value.tag = '/'.join([tag_split[0] + tag_suffix] + tag_split[1:]) - return summary.SerializeToString() - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument("--input_dir", type=str, required=True, help="either a directory containing subdirectories " - "train, val, test, etc, or a directory containing " - "the tfrecords") - parser.add_argument("--val_input_dir", type=str, help="directories containing the tfrecords. default: input_dir") - parser.add_argument("--logs_dir", default='logs', help="ignored if output_dir is specified") - parser.add_argument("--output_dir", help="output directory where json files, summary, model, gifs, etc are saved. " - "default is logs_dir/model_fname, where model_fname consists of " - "information from model and model_hparams") - parser.add_argument("--output_dir_postfix", default="") - parser.add_argument("--checkpoint", help="directory with checkpoint or checkpoint name (e.g. checkpoint_dir/model-200000)") - parser.add_argument("--resume", action='store_true', help='resume from lastest checkpoint in output_dir.') - - parser.add_argument("--dataset", type=str, help="dataset class name") - parser.add_argument("--dataset_hparams", type=str, help="a string of comma separated list of dataset hyperparameters") - parser.add_argument("--dataset_hparams_dict", type=str, help="a json file of dataset hyperparameters") - parser.add_argument("--model", type=str, help="model class name") - parser.add_argument("--model_hparams", type=str, help="a string of comma separated list of model hyperparameters") - parser.add_argument("--model_hparams_dict", type=str, help="a json file of model hyperparameters") - - parser.add_argument("--summary_freq", type=int, default=1000, help="save frequency of summaries (except for image and eval summaries) for train/validation set") - parser.add_argument("--image_summary_freq", type=int, default=5000, help="save frequency of image summaries for train/validation set") - parser.add_argument("--eval_summary_freq", type=int, default=25000, help="save frequency of eval summaries for train/validation set") - parser.add_argument("--accum_eval_summary_freq", type=int, default=100000, help="save frequency of accumulated eval summaries for validation set only") - parser.add_argument("--progress_freq", type=int, default=100, help="display progress every progress_freq steps") - parser.add_argument("--save_freq", type=int, default=5000, help="save frequence of model, 0 to disable") - - parser.add_argument("--aggregate_nccl", type=int, default=0, help="whether to use nccl or cpu for gradient aggregation in multi-gpu training") - parser.add_argument("--gpu_mem_frac", type=float, default=0, help="fraction of gpu memory to use") - parser.add_argument("--seed", type=int) - - args = parser.parse_args() - - if args.seed is not None: - tf.set_random_seed(args.seed) - np.random.seed(args.seed) - random.seed(args.seed) - - if args.output_dir is None: - list_depth = 0 - model_fname = '' - for t in ('model=%s,%s' % (args.model, args.model_hparams)): - if t == '[': - list_depth += 1 - if t == ']': - list_depth -= 1 - if list_depth and t == ',': - t = '..' - if t in '=,': - t = '.' - if t in '[]': - t = '' - model_fname += t - args.output_dir = os.path.join(args.logs_dir, model_fname) + args.output_dir_postfix - - if args.resume: - if args.checkpoint: - raise ValueError('resume and checkpoint cannot both be specified') - args.checkpoint = args.output_dir - - dataset_hparams_dict = {} - model_hparams_dict = {} - if args.dataset_hparams_dict: - with open(args.dataset_hparams_dict) as f: - dataset_hparams_dict.update(json.loads(f.read())) - if args.model_hparams_dict: - with open(args.model_hparams_dict) as f: - model_hparams_dict.update(json.loads(f.read())) - if args.checkpoint: - checkpoint_dir = os.path.normpath(args.checkpoint) - if not os.path.isdir(args.checkpoint): - checkpoint_dir, _ = os.path.split(checkpoint_dir) - if not os.path.exists(checkpoint_dir): - raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), checkpoint_dir) - with open(os.path.join(checkpoint_dir, "options.json")) as f: - print("loading options from checkpoint %s" % args.checkpoint) - options = json.loads(f.read()) - args.dataset = args.dataset or options['dataset'] - args.model = args.model or options['model'] - try: - with open(os.path.join(checkpoint_dir, "dataset_hparams.json")) as f: - dataset_hparams_dict.update(json.loads(f.read())) - except FileNotFoundError: - print("dataset_hparams.json was not loaded because it does not exist") - try: - with open(os.path.join(checkpoint_dir, "model_hparams.json")) as f: - model_hparams_dict.update(json.loads(f.read())) - except FileNotFoundError: - print("model_hparams.json was not loaded because it does not exist") - - print('----------------------------------- Options ------------------------------------') - for k, v in args._get_kwargs(): - print(k, "=", v) - print('------------------------------------- End --------------------------------------') - - VideoDataset = datasets.get_dataset_class(args.dataset) - train_dataset = VideoDataset( - args.input_dir, - mode='train', - hparams_dict=dataset_hparams_dict, - hparams=args.dataset_hparams) - val_dataset = VideoDataset( - args.val_input_dir or args.input_dir, - mode='val', - hparams_dict=dataset_hparams_dict, - hparams=args.dataset_hparams) - if val_dataset.hparams.long_sequence_length != val_dataset.hparams.sequence_length: - # the longer dataset is only used for the accum_eval_metrics - long_val_dataset = VideoDataset( - args.val_input_dir or args.input_dir, - mode='val', - hparams_dict=dataset_hparams_dict, - hparams=args.dataset_hparams) - long_val_dataset.set_sequence_length(val_dataset.hparams.long_sequence_length) - else: - long_val_dataset = None - - variable_scope = tf.get_variable_scope() - variable_scope.set_use_resource(True) - - VideoPredictionModel = models.get_model_class(args.model) - hparams_dict = dict(model_hparams_dict) - hparams_dict.update({ - 'context_frames': train_dataset.hparams.context_frames, - 'sequence_length': train_dataset.hparams.sequence_length, - 'repeat': train_dataset.hparams.time_shift, - }) - model = VideoPredictionModel( - hparams_dict=hparams_dict, - hparams=args.model_hparams, - aggregate_nccl=args.aggregate_nccl) - - batch_size = model.hparams.batch_size - train_tf_dataset = train_dataset.make_dataset_v2(batch_size)#Bing: adopt the meteo data prepartion here - train_iterator = train_tf_dataset.make_one_shot_iterator()#Bing:for era5, the problem happen in sess.run(feches) should come from here - # The `Iterator.string_handle()` method returns a tensor that can be evaluated - # and used to feed the `handle` placeholder. - train_handle = train_iterator.string_handle() - val_tf_dataset = val_dataset.make_dataset_v2(batch_size) - val_iterator = val_tf_dataset.make_one_shot_iterator() - val_handle = val_iterator.string_handle() - #iterator = tf.data.Iterator.from_string_handle( - # train_handle, train_tf_dataset.output_types, train_tf_dataset.output_shapes) - inputs = train_iterator.get_next() - - # inputs comes from the training dataset by default, unless train_handle is remapped to the val_handles - model.build_graph(inputs, finetune=True) - - if long_val_dataset is not None: - # separately build a model for the longer sequence. - # this is needed because the model doesn't support dynamic shapes. - long_hparams_dict = dict(hparams_dict) - long_hparams_dict['sequence_length'] = long_val_dataset.hparams.sequence_length - # use smaller batch size for longer model to prevenet running out of memory - long_hparams_dict['batch_size'] = model.hparams.batch_size // 2 - long_model = VideoPredictionModel( - mode="test", # to not build the losses and discriminators - hparams_dict=long_hparams_dict, - hparams=args.model_hparams, - aggregate_nccl=args.aggregate_nccl) - tf.get_variable_scope().reuse_variables() - long_model.build_graph(long_val_dataset.make_batch(batch_size)) - else: - long_model = None - - if not os.path.exists(args.output_dir): - os.makedirs(args.output_dir) - with open(os.path.join(args.output_dir, "options.json"), "w") as f: - f.write(json.dumps(vars(args), sort_keys=True, indent=4)) - with open(os.path.join(args.output_dir, "dataset_hparams.json"), "w") as f: - f.write(json.dumps(train_dataset.hparams.values(), sort_keys=True, indent=4)) - with open(os.path.join(args.output_dir, "model_hparams.json"), "w") as f: - f.write(json.dumps(model.hparams.values(), sort_keys=True, indent=4)) - - with tf.name_scope("parameter_count"): - # exclude trainable variables that are replicas (used in multi-gpu setting) - trainable_variables = set(tf.trainable_variables()) & set(model.saveable_variables) - parameter_count = tf.reduce_sum([tf.reduce_prod(tf.shape(v)) for v in trainable_variables]) - - saver = tf.train.Saver(var_list=model.saveable_variables, max_to_keep=2) - - # None has the special meaning of evaluating at the end, so explicitly check for non-equality to zero - if (args.summary_freq != 0 or args.image_summary_freq != 0 or - args.eval_summary_freq != 0 or args.accum_eval_summary_freq != 0): - summary_writer = tf.summary.FileWriter(args.output_dir) - - gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=args.gpu_mem_frac, allow_growth=True) - config = tf.ConfigProto(gpu_options=gpu_options, allow_soft_placement=True) - global_step = tf.train.get_or_create_global_step() - max_steps = model.hparams.max_steps - with tf.Session(config=config) as sess: - print("parameter_count =", sess.run(parameter_count)) - sess.run(tf.global_variables_initializer()) - sess.run(tf.local_variables_initializer()) - #coord = tf.train.Coordinator() - #threads = tf.train.start_queue_runners(sess = sess, coord = coord) - print("Init done: {sess.run(tf.local_variables_initializer())}%") - model.restore(sess, args.checkpoint) - print("Restore processed finished") - sess.run(model.post_init_ops) - print("Model run started") - val_handle_eval = sess.run(val_handle) - print("val handle done") - sess.graph.finalize() - print("graph inalize done") - start_step = sess.run(global_step) - print("global step done") - - def should(step, freq): - if freq is None: - return (step + 1) == (max_steps - start_step) - else: - return freq and ((step + 1) % freq == 0 or (step + 1) in (0, max_steps - start_step)) - - def should_eval(step, freq): - # never run eval summaries at the beginning since it's expensive, unless it's the last iteration - return should(step, freq) and (step >= 0 or (step + 1) == (max_steps - start_step)) - - # start at one step earlier to log everything without doing any training - # step is relative to the start_step - for step in range(-1, max_steps - start_step): - if step == 1: - # skip step -1 and 0 for timing purposes (for warmstarting) - start_time = time.time() - - fetches = {"global_step": global_step} - if step >= 0: - fetches["train_op"] = model.train_op - if should(step, args.progress_freq): - fetches['d_loss'] = model.d_loss - fetches['g_loss'] = model.g_loss - fetches['d_losses'] = model.d_losses - fetches['g_losses'] = model.g_losses - if isinstance(model.learning_rate, tf.Tensor): - fetches["learning_rate"] = model.learning_rate - if should(step, args.summary_freq): - fetches["summary"] = model.summary_op - if should(step, args.image_summary_freq): - fetches["image_summary"] = model.image_summary_op - if should_eval(step, args.eval_summary_freq): - fetches["eval_summary"] = model.eval_summary_op - - run_start_time = time.time() - results = sess.run(fetches) #fetch the elements in dictinoary fetch - - run_elapsed_time = time.time() - run_start_time - if run_elapsed_time > 1.5 and step > 0 and set(fetches.keys()) == {"global_step", "train_op"}: - print('running train_op took too long (%0.1fs)' % run_elapsed_time) - - if (should(step, args.summary_freq) or - should(step, args.image_summary_freq) or - should_eval(step, args.eval_summary_freq)): - val_fetches = {"global_step": global_step} - if should(step, args.summary_freq): - val_fetches["summary"] = model.summary_op - if should(step, args.image_summary_freq): - val_fetches["image_summary"] = model.image_summary_op - if should_eval(step, args.eval_summary_freq): - val_fetches["eval_summary"] = model.eval_summary_op - val_results = sess.run(val_fetches, feed_dict={train_handle: val_handle_eval}) - for name, summary in val_results.items(): - if name == 'global_step': - continue - val_results[name] = add_tag_suffix(summary, '_1') - - if should(step, args.summary_freq): - print("recording summary") - summary_writer.add_summary(results["summary"], results["global_step"]) - summary_writer.add_summary(val_results["summary"], val_results["global_step"]) - print("done") - if should(step, args.image_summary_freq): - print("recording image summary") - summary_writer.add_summary(results["image_summary"], results["global_step"]) - summary_writer.add_summary(val_results["image_summary"], val_results["global_step"]) - print("done") - if should_eval(step, args.eval_summary_freq): - print("recording eval summary") - summary_writer.add_summary(results["eval_summary"], results["global_step"]) - summary_writer.add_summary(val_results["eval_summary"], val_results["global_step"]) - print("done") - if should_eval(step, args.accum_eval_summary_freq): - val_datasets = [val_dataset] - val_models = [model] - if long_model is not None: - val_datasets.append(long_val_dataset) - val_models.append(long_model) - for i, (val_dataset_, val_model) in enumerate(zip(val_datasets, val_models)): - sess.run(val_model.accum_eval_metrics_reset_op) - # traverse (roughly up to rounding based on the batch size) all the validation dataset - accum_eval_summary_num_updates = val_dataset_.num_examples_per_epoch() // val_model.hparams.batch_size - val_fetches = {"global_step": global_step, "accum_eval_summary": val_model.accum_eval_summary_op} - for update_step in range(accum_eval_summary_num_updates): - print('evaluating %d / %d' % (update_step + 1, accum_eval_summary_num_updates)) - val_results = sess.run(val_fetches, feed_dict={train_handle: val_handle_eval}) - accum_eval_summary = add_tag_suffix(val_results["accum_eval_summary"], '_%d' % (i + 1)) - print("recording accum eval summary") - summary_writer.add_summary(accum_eval_summary, val_results["global_step"]) - print("done") - if (should(step, args.summary_freq) or should(step, args.image_summary_freq) or - should_eval(step, args.eval_summary_freq) or should_eval(step, args.accum_eval_summary_freq)): - summary_writer.flush() - if should(step, args.progress_freq): - # global_step will have the correct step count if we resume from a checkpoint - # global step is read before it's incremented - steps_per_epoch = train_dataset.num_examples_per_epoch() / batch_size - train_epoch = results["global_step"] / steps_per_epoch - print("progress global step %d epoch %0.1f" % (results["global_step"] + 1, train_epoch)) - if step > 0: - elapsed_time = time.time() - start_time - average_time = elapsed_time / step - images_per_sec = batch_size / average_time - remaining_time = (max_steps - (start_step + step + 1)) * average_time - print(" image/sec %0.1f remaining %dm (%0.1fh) (%0.1fd)" % - (images_per_sec, remaining_time / 60, remaining_time / 60 / 60, remaining_time / 60 / 60 / 24)) - - if results['d_losses']: - print("d_loss", results["d_loss"]) - for name, loss in results['d_losses'].items(): - print(" ", name, loss) - if results['g_losses']: - print("g_loss", results["g_loss"]) - for name, loss in results['g_losses'].items(): - print(" ", name, loss) - if isinstance(model.learning_rate, tf.Tensor): - print("learning_rate", results["learning_rate"]) - - if should(step, args.save_freq): - print("saving model to", args.output_dir) - saver.save(sess, os.path.join(args.output_dir, "model"), global_step=global_step) - print("done") - -if __name__ == '__main__': - main() diff --git a/workflow_parallel_frame_prediction/DataExtraction/external_function.py b/video_prediction_savp/utils/external_function.py similarity index 100% rename from workflow_parallel_frame_prediction/DataExtraction/external_function.py rename to video_prediction_savp/utils/external_function.py diff --git a/workflow_parallel_frame_prediction/DataExtraction/shiftgrid.py b/video_prediction_savp/utils/shiftgrid.py similarity index 100% rename from workflow_parallel_frame_prediction/DataExtraction/shiftgrid.py rename to video_prediction_savp/utils/shiftgrid.py diff --git a/workflow_parallel_frame_prediction/DataExtraction/prepare_era5_data.py b/video_prediction_savp/video_prediction/datasets/prepare_era5_data.py similarity index 100% rename from workflow_parallel_frame_prediction/DataExtraction/prepare_era5_data.py rename to video_prediction_savp/video_prediction/datasets/prepare_era5_data.py diff --git a/workflow_parallel_frame_prediction/DataPreprocess/process_netCDF_v2.py b/video_prediction_savp/video_prediction/datasets/process_netCDF_v2.py similarity index 100% rename from workflow_parallel_frame_prediction/DataPreprocess/process_netCDF_v2.py rename to video_prediction_savp/video_prediction/datasets/process_netCDF_v2.py diff --git a/workflow_parallel_frame_prediction/DataExtraction/helper_single_master.py b/workflow_parallel_frame_prediction/DataExtraction/helper_single_master.py deleted file mode 100644 index a26d7639..00000000 --- a/workflow_parallel_frame_prediction/DataExtraction/helper_single_master.py +++ /dev/null @@ -1,245 +0,0 @@ -from mpi4py import MPI -from os import walk -import os -import sys -import subprocess -import logging -import time -import hashlib -import argparse -from os import listdir -from os.path import isfile, join - -# ini. MPI -comm = MPI.COMM_WORLD -my_rank = comm.Get_rank() # rank of the node -p = comm.Get_size() # number of assigned nods -my_rank = comm.Get_rank() # rank of the node - - -# ======================= List of functions ====================================== # -if my_rank == 0: # node is master - - logger = logging.getLogger(__file__) - logger.addHandler(logging.StreamHandler(sys.stdout)) - - -def directory_scanner(source_path,load_level): - # Take a look inside a directories and make a list of ll the folders, sub directories, number of the files and size - # NOTE : It will neglect if there is a sub-directories inside directories!!! - # NOTE : It will discriminate between the load level : sub-directories / Files - - dir_detail_list = [] # directories details - list_items_to_process = [] - total_size_source = 0 - total_num_files = 0 - list_directories = [] - - ## =================== Here will be for the Files ================= ## - - if load_level == 1: - - # Listing all the files in the directory - for dirpath, dirnames, filenames in os.walk(source_path): - list_items_to_process.extend(filenames) - - for f in list_items_to_process : - path = source_path +"/"+ str(f) - statinfo = os.stat(path) - size = statinfo.st_size - total_size_source = total_size_source + int(size) - - total_num_files = len(list_items_to_process) # number of the files in the source - total_num_directories = int(0) # TODO need to unify the concept as the number of items - - ## ===================== Here will be for the directories ========== ## - - if load_level == 0: - list_directories = os.listdir(source_path) - - for d in list_directories: - path = source_path + d - if os.path.isdir(path): - list_items_to_process.append(d) - list_items_to_process.sort() - num_files = 0 - # size of the files and subdirectories - size_dir = subprocess.check_output(['du', '-sc', path]) - splitted = size_dir.split() # fist item is the size of the folder - size = (splitted[0]) - num_files = len([f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]) - dir_detail_list.extend([d, size, num_files]) - total_num_files = total_num_files + int(num_files) - total_size_source = total_size_source + int(size) - - else: - message = path,'does not exist' - logging.error(message) - - - total_num_directories = int(len(list_directories)) - - ## ======================= End of the Directory case =================== ## - total_size_source = float(total_size_source / 1000000) # human readable size source - - logger.info("=== Directory Scanner output ===") - message = 'Total size of the source directory is:' + str(total_size_source) + 'Gb.' - logger.info(message) - message = "Total number of the files in the source directory is: " + str(total_num_files) - logger.info(message) - message = "Total number of the directories in the source directory is: " + str(total_num_directories) - logger.info(message) - - # Unifying the naming of this section for both cases : Sub - Directory or File - # dir_detail_list == > Including the name of the directories, size and number of teh files in each directory / for files is empty - # list_items_to_process === > List of items to process (Sub-Directories / Files) - # total_size_source === > Total size of the items to process - # total_num_files === > for Sub - Directories : sum of all files in different directories / for Files is sum of all - # total_num_directories === > for Files = 0 - - return dir_detail_list, list_items_to_process, total_size_source, total_num_files, total_num_directories - -# Source - Directoy -# Destination Rirectory -# Dir_detail_list -# list_items_to_process -# load level - -def data_structure_builder (source_dir, destination_dir, dir_detail_list, list_items_to_process,load_level): - - - if not os.path.exists(destination_dir): # check if the Destination dir. is existing - os_command = ("mkdir " + destination_dir) - os.system(os_command) - logger.info('destination path is created') - else: - logger.info('The destination path exists') - - - os.chdir(destination_dir) # chnage the directory to the destination - - if load_level == 0: - logging.info('Load Level = 0 : Data Sctructure will be build') - - for dir_name in list_items_to_process: - #print(dir_name) - dir_path = destination_dir + dir_name - - # TODO : os.mkdir() it can be cleaned up to use the OS predifnie functions - if not os.path.exists(dir_path): - #print(dir_name + " will be created ") - os_command = ("mkdir " + dir_name) - os.system(os_command) - logging.info(dir_name + " is created ") - - - if load_level == 1: - logger.info('Load Level = 1 : File will be processed') - - return - - - -def load_distributor(dir_detail_list, list_items_to_process, total_size_source, total_num_files, total_num_directories,load_level, processor_num): - firs_slave_processor_id = 1 - # create a dictionary with p number of keys - # for each directory they add the name to one of the keys - # here we define the first availabe slave node as well - transfer_dict = dict.fromkeys(list(range(firs_slave_processor_id, processor_num))) - print(transfer_dict) - logger.info("The follwoing is in the load Balancer ") - logger.info(transfer_dict) - logger.info(list_items_to_process) - logger.info(total_num_directories) - logger.info(total_num_files) - - # package_counter = 0 possibility to use the counter to fill - counter = firs_slave_processor_id # this is the ID of the first available slave to p! - - if load_level == 0: - for Directory_counter in range(0, total_num_directories): - if transfer_dict[counter] is None: # if the value for the key is None add to it - transfer_dict[counter] = list_items_to_process[Directory_counter] - else: # if key has a value join the new value to the old value - transfer_dict[counter] = "{};{}".format(transfer_dict[counter], list_items_to_process[Directory_counter]) - counter = counter + 1 - if counter == processor_num: - counter = firs_slave_processor_id - - if load_level == 1: - for File_counter in range(0, total_num_files): - if transfer_dict[counter] is None: # if the value for the key is None add to it - #print(" M1: New key made for a free processor number {my_rank}".format(my_rank = counter)) - # statemnet if we have more than number of the files processor available - if counter > len(list_items_to_process) + (firs_slave_processor_id - 1 ): - transfer_dict[counter] = None - else: - transfer_dict[counter] = list_items_to_process[File_counter] - - - - else: # if key has a value join the new value to the old value - transfer_dict[counter] = "{};{}".format(transfer_dict[counter], list_items_to_process[File_counter]) - counter = counter + 1 - if counter == processor_num: - counter = firs_slave_processor_id - - logging.info(transfer_dict) - return transfer_dict - -def sync_file(source_path, destination_dir, job_name, rsync_status): - rsync_msg = ("rsync -r " + source_path + job_name + "/" + " " + destination_dir + "/" + job_name) - # print('Node:', str(my_rank),'will execute :', rsync_str,'\r\n') - # sync the assigned folder - - if rsync_status == 1: - os.system(rsync_msg) - - return - - - -def hash_directory(source_path,job_name,hash_rep_file,input_status): - #sha256_hash = hashlib.sha256() - md5_hash = hashlib.md5() - - ########## Create a hashed file repasitory for direcotry(ies) assigned to node ####### - hash_repo_text = input_status + "_"+job_name +"_hashed.txt" - os.chdir(hash_rep_file) - hashed_text_note=open(hash_repo_text,"w+") - - # job_name is the name of the subdirectory that is going to be processed - directory_to_process = source_path + job_name - # print(directory_to_process) - files_list = [] - for dirpath, dirnames, filenames in os.walk(directory_to_process): - files_list.extend(filenames) - - os.chdir(directory_to_process) # change to the working directory - - for file_to_process in filenames: - - ## ======= this is the sha256 checksum ========= # - #with open(file_to_process,"rb") as f: - # # Read and update hash in chunks of 4K - # for byte_block in iter(lambda: f.read(4096),b""): - # sha256_hash.update(byte_block) - # hashed_file = sha256_hash.hexdigest() - - with open(file_to_process,"rb") as f: - # Read and update hash in chunks of 4K - for byte_block in iter(lambda: f.read(4096),b""): - md5_hash.update(byte_block) - hashed_file = md5_hash.hexdigest() - - hashed_text_note.write(hashed_file) - - return - -def md5(fname): - md5_hash = hashlib.md5() - with open(fname,"rb") as f: - # Read and update hash in chunks of 4K - for byte_block in iter(lambda: f.read(4096),b""): - md5_hash.update(byte_block) - return md5_hash.hexdigest() diff --git a/workflow_parallel_frame_prediction/DataExtraction/main_single_master.py b/workflow_parallel_frame_prediction/DataExtraction/main_single_master.py deleted file mode 100644 index fda72c67..00000000 --- a/workflow_parallel_frame_prediction/DataExtraction/main_single_master.py +++ /dev/null @@ -1,257 +0,0 @@ -from mpi4py import MPI -from os import walk -import sys -import subprocess -import logging -import time -import shutil -import glob -import argparse -import os - - -from helper_single_master import directory_scanner -from helper_single_master import load_distributor -from helper_single_master import hash_directory -from helper_single_master import data_structure_builder -from helper_single_master import md5 - -from prepare_era5_data import prepare_era5_data_one_file - -# How to Run it! -# mpirun -np 6 python mpi_stager_v2.py -# mpiexec -np 6 python mpi_stager_v2.py - - -def main(): - parser=argparse.ArgumentParser() - parser.add_argument("--job_id",type=int,default=100) - parser.add_argument("--source_dir",type=str,default="//home/a.mozaffari/data_era5/2017/") - parser.add_argument("--destination_dir",type=str,default="/home/a.mozaffari/data_dest/") - parser.add_argument("--log_temp",type=str,default="log_temp") - parser.add_argument("--checksum_status",type=int,default = 0) - parser.add_argument("--rsync_status",type=int,default=0) - parser.add_argument("--load_level",type=int,default=0) - parser.add_argument("--clear_destination",type=int,default=1) - args = parser.parse_args() - # for the local machine test - current_path = os.getcwd() - job_id = args.job_id - source_dir = args.source_dir - destination_dir = args.destination_dir - checksum_status = args.checksum_status - rsync_status = args.rsync_status - clear_destination = args.clear_destination - log_temp = args.log_temp - - - # for the local machine test - current_path = os.path.dirname(os.path.abspath(__file__)) - os.chdir(current_path) - time.sleep(0) - -# ini. MPI - comm = MPI.COMM_WORLD - my_rank = comm.Get_rank() # rank of the node - p = comm.Get_size() # number of assigned nods - firs_slave_processor_id = 1 - - - # ==================================== Master Logging ==================================================== # - # DEBUG: Detailed information, typically of interest only when diagnosing problems. - # INFO: Confirmation that things are working as expected. - # WARNING: An indication that something unexpected happened, or indicative of some problem in the near - # ERROR: Due to a more serious problem, the software has not been able to perform some function. - # CRITICAL: A serious error, indicating that the program itself may be unable to continue running. - # It will copy the logging messages to the stdout, for the case of container version on HPC - - if my_rank == 0: # node is master - - # delete the general logger if exist - logger_path = current_path + '/distribution_job_{job_id}.log'.format(job_id=job_id) - if os.path.isfile(logger_path): - print("Logger Exists -> Logger Deleted") - os.remove(logger_path) - logging.basicConfig(filename='distribution_job_{job_id}.log'.format(job_id=job_id), level=logging.DEBUG, - format='%(asctime)s:%(levelname)s:%(message)s') - logger = logging.getLogger(__file__) - logger.addHandler(logging.StreamHandler(sys.stdout)) - start = time.time() # start of the MPI - -# check the existence of the source path : - if not os.path.exists(source_dir): # check if the source dir. is existing - if my_rank == 0: - logger.critical('The source does not exist') - message_out = "Source : {source} is not existing -> Abort".format(source=source_dir) - logger.info('exit status : 1') - sys.exit(1) - -# Check if the destination is existing, if so, it will delete and recreate the destination_dir - if os.path.exists(destination_dir): - if my_rank == 0: - logger.info('The destination exist') - if clear_destination == 1: - shutil.rmtree(destination_dir) - os.mkdir(destination_dir) - logger.critical("Destination : {destination} exist -> Remove and Re-Create".format(destination=destination_dir)) - print("Destination : {destination} exist -> Remove and Re-Create".format(destination=destination_dir)) - - else: - logger.critical("Destination : {destination} exist -> will not be removed (caution : overwrite)".format(destination=destination_dir)) - print("Destination : {destination} exist -> will not be rmeoved (caution : overwrite)".format(destination=destination_dir)) - - - - # 20200630 +++ Scarlet - else: - if my_rank == 0: - os.makedirs(destination_dir) #, exist_ok=True) - logger.info("Destination : {destination} does not exist -> Create".format(destination=destination_dir)) - print("Destination : {destination} does not exist -> Create".format(destination=destination_dir)) - - # 20200630 --- Scarlet - - - # Create a log folder for slave-nodes to write down their processes - slave_log_path = os.path.join(destination_dir,log_temp) - - if my_rank == 0: - if os.path.exists(slave_log_path) == False: - # 20200630 Scarlet - #os.mkdir(slave_log_path) - os.makedirs(slave_log_path) - - if my_rank == 0: # node is master - - # ==================================== Master : Directory scanner {Parent level load level = 0} ================================= # - - logger.info("The source path is : {path}".format(path=source_dir)) - logger.info("The destination path is : {path}".format(path=destination_dir)) - logger.info("==== Directory scanner : start ====") - load_level = 0 - ret_dir_scanner = directory_scanner(source_dir,load_level) - #print(ret_dir_scanner) - - # Unifying the naming of this section for both cases : Sub - Directory or File - # dir_detail_list == > Including the name of the directories, size and number of teh files in each directory / for files is empty - # list_items_to_process === > List of items to process (Sub-Directories / Files) - # total_size_source === > Total size of the items to process - # total_num_files === > for Sub - Directories : sum of all files in different directories / for Files is sum of all - # total_num_directories === > for Files = 0 - - dir_detail_list = ret_dir_scanner[0] - list_items_to_process = ret_dir_scanner[1] - total_size_source = ret_dir_scanner[2] - total_num_files = ret_dir_scanner[3] - total_num_dir = ret_dir_scanner[4] - logger.info("==== Directory scanner : end ====") - - # ================================= Master : Data Structure Builder {Parent level load level = 0} ========================= # - - logger.info("==== Data Structure Builder : start ====") - data_structure_builder(source_dir, destination_dir, dir_detail_list, list_items_to_process,load_level) - logger.info("==== Data Structure Builder : end ====") - # message to inform the slaves that they will recive #Batch of messages including the logger_p - batch_info = list_items_to_process - for slaves in range (1,p): - comm.send(batch_info, dest=slaves) - - for batch_counter in range (0,len(batch_info)): - #relative_source = source_dir + str(batch_info[batch_counter]) +"/" - relative_source = os.path.join(source_dir,str(batch_info[batch_counter])) - print(relative_source) - logger.info("MA{my_rank}: Next to be processed is {task} loacted in {path} ".format(my_rank = my_rank,task=batch_info[batch_counter], path=relative_source)) - load_level = 1 # it will process the files in the relative source - - #________ Directory Scanner ______# - relative_ret_dir_scanner = directory_scanner(relative_source,load_level) - relative_dir_detail_list = relative_ret_dir_scanner[0] - relative_list_items_to_process = relative_ret_dir_scanner[1] - relative_total_size_source = relative_ret_dir_scanner[2] - relative_total_num_files = relative_ret_dir_scanner[3] - relative_total_num_dir = relative_ret_dir_scanner[4] - #________ Load Distribution ________# - relative_ret_load_balancer = load_distributor(relative_dir_detail_list, relative_list_items_to_process, relative_total_size_source, relative_total_num_files, relative_total_num_dir,load_level, p) - relative_transfer_dict = relative_ret_load_balancer - logger.info(relative_transfer_dict) - - #________ Communication ________# - - for processor in range(firs_slave_processor_id, p): - broadcast_list = relative_transfer_dict[processor] - comm.send(broadcast_list, dest=processor) - - receive_counter = 0 - total_number_messages = (p-1) * len(batch_info) - 1 - while receive_counter <= total_number_messages: - message_in = comm.recv() - logger.info("MA{my_rank}: S{message_in} ".format(my_rank=my_rank,message_in=message_in)) - receive_counter = receive_counter + 1 - - - # Cleaning up the slaves temprory log file, if it is empty. - if len(os.listdir(slave_log_path) ) == 0: - print("Temprory log file is empty, it is deleted") - os.removedirs(slave_log_path) - - - end = time.time() - termination_message = "MA{my_rank}: Sucssfully terminated with total time : {wall_time}".format(my_rank=my_rank,wall_time= end-start) - logger.info(termination_message) - sys.exit(0) - - else: # Processor is slave - - # ============================================= Slave : Send / Receive ============================================ # - # recive the #Batch process that will be recived - batch_info = comm.recv(source = 0) - #print("S{my_rank} will receive {todo_message} batch of task to process".format(my_rank=my_rank, todo_message=len(batch_info))) - batch_counter = 0 - - # here will be a loop around all the #batchs - - while batch_counter <= len(batch_info) -1: - message_in = comm.recv(source = 0) - relative_source_directory = os.path.join(source_dir,str(batch_info[batch_counter])) - relative_destination_directory = os.path.join(destination_dir,str(batch_info[batch_counter])) - - if message_in is None: # in case more than number of the dir. processor is assigned ! - slave_out_message = "{my_rank} is idle".format(my_rank=my_rank) - # comm.send(message_out, dest=1) - - else: # if the Slave node has joblist to do - job_list = message_in.split(';') - for job_count in range(0, len(job_list)): - job = job_list[job_count] # job is the name of the directory(ies) assigned to slave_node - #print(job) - if rsync_status == 1: - # prepare the rsync commoand to be excexuted by the worker node - rsync_message = "rsync {relative_source_directory}/{job} {relative_destination_directory}/{job}".format(relative_source_directory=relative_source_directory,job=job, relative_destination_directory=relative_destination_directory) - os.system(rsync_message) - #slave_out_message= " RSYNC process" - else : - ## @Bing here is the job for the slaves - print("S{my_rank} will execute era5 preperation on {job}".format(my_rank=my_rank, job=job)) - prepare_era5_data_one_file(src_file=job,directory_to_process=relative_source_directory, target=job, target_dir=relative_destination_directory) - - - - #if job.endswith(".nc"): - # if os.path.exists(os.path.join(relative_destination_directory, job)): - # print("{job} is has been processed in directory {directory}".format(job=job,directory=relative_destination_directory)) - #else: - # prepare_era5_data_one_file(src_file=job,directory_to_process=relative_source_directory, target=job, target_dir=relative_destination_directory) - # print("File {job} in directory {directory} has been processed in directory".format(job=job,directory=relative_destination_directory)) - # - #slave_out_message = " {in_message} process".format(in_message=my_rank) - # Generate a hash of the output - - message_out = "{my_rank}: is finished the {in_message} .".format(my_rank=my_rank,in_message=batch_info[batch_counter]) - comm.send(message_out, dest=0) - batch_counter = batch_counter + 1 - - MPI.Finalize() - - -if __name__ == "__main__": - main() diff --git a/workflow_parallel_frame_prediction/DataExtraction/readme.md b/workflow_parallel_frame_prediction/DataExtraction/readme.md deleted file mode 100644 index 9e97dae8..00000000 --- a/workflow_parallel_frame_prediction/DataExtraction/readme.md +++ /dev/null @@ -1,2 +0,0 @@ -`source create_env_zam347.sh {MPI}` <br/> -`mpirun -np {number of processors max 13 on zam347} python main_single_master.py` \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/DataExtraction/submitJob.sh b/workflow_parallel_frame_prediction/DataExtraction/submitJob.sh deleted file mode 100755 index 2e55e377..00000000 --- a/workflow_parallel_frame_prediction/DataExtraction/submitJob.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -x -#SBATCH --account=deepacf -#SBATCH --nodes=1 -#SBATCH --ntasks=1 -##SBATCH --ntasks-per-node=1 -#SBATCH --cpus-per-task=1 -#SBATCH --output=pystager-out.%j -#SBATCH --error=pystager-err.%j -#SBATCH --time=00:20:00 -#SBATCH --partition=devel -#SBATCH --mail-type=ALL -#SBATCH --mail-user=b.gong@fz-juelich.de -##jutil env activate -p deepacf - -module --force purge -module /usr/local/software/jureca/OtherStages -module load Stages/2019a -module load Intel/2019.3.199-GCC-8.3.0 ParaStationMPI/5.2.2-1 -module load mpi4py/3.0.1-Python-3.6.8 - -#srun python mpi_stager_v2.py --source_dir /p/fastdata/slmet/slmet111/met_data/ecmwf/era5/#nc/2017/ --destination_dir /p/scratch/deepacf/bing/extractedData -srun python Extract_data_for_testing.py diff --git a/workflow_parallel_frame_prediction/DataPostprocess/Stager_devel_N_24_evaluation.sh b/workflow_parallel_frame_prediction/DataPostprocess/Stager_devel_N_24_evaluation.sh deleted file mode 100755 index 1aa0ae9a..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/Stager_devel_N_24_evaluation.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -#SBATCH --account=jjsc42 -# budget account where contingent is taken from# TASKS = NODES * GPUS_PER_NODE -#SBATCH --nodes=3 -#SBATCH --ntasks-per-node=4 -#SBATCH --ntasks=12 -# can be omitted if --nodes and --ntasks-per-node -# are given -# SBATCH --cpus-per-task=1 -# for OpenMP/hybrid jobs only -#SBATCH --output=horovod-4ntasks%j.out -# if keyword omitted: Default is slurm-%j.out in -# the submission directory (%j is replaced by -# the job ID). -#SBATCH --error=horovod-4ntasks%j.err -# if keyword omitted: Default is slurm-%j.out in -# the submission directory. -#SBATCH --time=20:00:00 -#SBATCH --gres=gpu:4 -#SBATCH --partition=gpus -#SBATCH --mail-user=b.gong@fz-juelich.de -#SBATCH --mail-type=ALL - -#create a folder to save the output - -module --force purge -module --force purge -module load Stages/Devel-2019a -module load GCC/8.3.0 -module load MVAPICH2/2.3.2-GDR -#module /usr/local/software/jureca/OtherStages -module load Stages/2019a -module load GCCcore/.8.3.0 -module load cuDNN/7.5.1.10-CUDA-10.1.105 -module load Horovod/0.16.2-GPU-Python-3.6.8 -module load Keras/2.2.4-GPU-Python-3.6.8 -#module load Intel/2019.3.199-GCC-8.3.0 ParaStationMPI/5.2.2-1-mt -#module load mpi4py/3.0.1-Python-3.6.8 - -srun python3.6 kitti_evaluate_parallel.py diff --git a/workflow_parallel_frame_prediction/DataPostprocess/data_utils.py b/workflow_parallel_frame_prediction/DataPostprocess/data_utils.py deleted file mode 100755 index 8751fc42..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/data_utils.py +++ /dev/null @@ -1,164 +0,0 @@ -import hickle as hkl -import numpy as np -from keras import backend as K -from keras.preprocessing.image import Iterator - - -import inspect -print(inspect.getmembers(hkl,predicate=inspect.ismethod)) - -# Data generator that creates sequences for input into PredNet. -class SequenceGenerator(Iterator): - def __init__(self, data_file, source_file, nt, - batch_size=8, shuffle=False, seed=None, - output_mode='error', sequence_start_mode='all', N_seq=None, - data_format=K.image_data_format()): - self.X = hkl.load(data_file) # X will be like (n_images, nb_cols, nb_rows, nb_channels) - self.sources = hkl.load(source_file) # source for each image so when creating sequences can assure that consecutive frames are from same video - self.nt = nt - self.batch_size = batch_size - self.data_format = data_format - assert sequence_start_mode in {'all', 'unique'}, 'sequence_start_mode must be in {all, unique}' - self.sequence_start_mode = sequence_start_mode - assert output_mode in {'error', 'prediction'}, 'output_mode must be in {error, prediction}' - self.output_mode = output_mode - - if self.data_format == 'channels_first': - self.X = np.transpose(self.X, (0, 3, 1, 2)) - self.im_shape = self.X[0].shape - - if self.sequence_start_mode == 'all': # allow for any possible sequence, starting from any frame - #bing - #self.possible_starts = np.array([i for i in range(self.X.shape[0] - self.nt) if self.sources[i] == self.sources[i + self.nt - 1]]) - self.possible_starts = np.array([i for i in range(self.X.shape[0] - self.nt)]) - elif self.sequence_start_mode == 'unique': #create sequences where each unique frame is in at most one sequence - curr_location = 0 - possible_starts = [] - while curr_location < self.X.shape[0] - self.nt + 1: - if self.sources[curr_location] == self.sources[curr_location + self.nt - 1]: - possible_starts.append(curr_location) - curr_location += self.nt - else: - curr_location += 1 - self.possible_starts = possible_starts - - if shuffle: - self.possible_starts = np.random.permutation(self.possible_starts) - if N_seq is not None and len(self.possible_starts) > N_seq: # select a subset of sequences if want to - self.possible_starts = self.possible_starts[:N_seq] - self.N_sequences = len(self.possible_starts) - print("N_sequences", self.N_sequences) - super(SequenceGenerator, self).__init__(len(self.possible_starts), batch_size, shuffle, seed) - - def __getitem__(self, null): - return self.next() - - def next(self): - with self.lock: - current_index = (self.batch_index * self.batch_size) % self.n - index_array, current_batch_size = next(self.index_generator), self.batch_size - batch_x = np.zeros((current_batch_size, self.nt) + self.im_shape, np.float32) - for i, idx in enumerate(index_array): - idx = self.possible_starts[idx] - batch_x[i] = self.preprocess(self.X[idx:idx+self.nt]) - if self.output_mode == 'error': # model outputs errors, so y should be zeros - batch_y = np.zeros(current_batch_size, np.float32) - elif self.output_mode == 'prediction': # output actual pixels - batch_y = batch_x - return batch_x, batch_y - - def preprocess(self, X): - ### Normalization after extrema cut off: ### - #cut maxs & mins to mean+3*std & mean-3*std of training set for each parameter - #x_cut = np.zeros(shape=X.shape) - #x_cut = X*1 #pass X by value and not by reference - #x_cut[:,:,:,0][X[:,:,:,0]>311.5]=311.5 #set T2 upper limit - #x_cut[:,:,:,0][X[:,:,:,0]<258.9]=258.9 #set T2 lower limit - #x_cut[:,:,:,1][X[:,:,:,1]>104635.2]=104635.2 #set GP upper limit - #x_cut[:,:,:,1][X[:,:,:,1]<98205.6]=98205.6 #set GP lower limit ###Caution: Drastical cut ### - #x_cut[:,:,:,2][X[:,:,:,2]>6209.5]=6209.5 #set GPH upper limit ###Caution: Unnecessary as it succeeds max GPH ### - #x_cut[:,:,:,2][X[:,:,:,2]<5005.8]=5005.8 #set GPH lower limit - #normalize X based on max and min values(equals upper and lower limits except highCutGPH) - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (x_cut[:,:,:,0]-258.9)/(311.5-258.9) - #x_processed[:,:,:,1] = (x_cut[:,:,:,1]-98205.6)/(104635.2-98205.6) - #x_processed[:,:,:,2] = (x_cut[:,:,:,2]-5005.8)/(6007.097417091836-5005.8) #GPH max stays; see above - - ### 'Standard' normalization: (x-min(x))/(max(x)-min(x)) ### - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-93401.125)/(105391.4375-93401.125) - #x_processed[:,:,:,2] = (X[:,:,:,2]-4836.070232780612)/(6007.097417091836-4836.070232780612) - - ### t2only 'Standard' normalization: (x-min(x))/(max(x)-min(x)) ### - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,2] = (X[:,:,:,2]-235.2141571044922)/(321.46630859375-235.2141571044922) - - ### t2_2MSL_1 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,2] = (X[:,:,:,2]-93401.125)/(105391.4375-93401.125) - - ### t2_1MSL_2 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-93401.125)/(105391.4375-93401.125) - #x_processed[:,:,:,2] = (X[:,:,:,2]-93401.125)/(105391.4375-93401.125) - - ### t2_2gph500_1 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,2] = (X[:,:,:,2]-4836.070232780612)/(6007.097417091836-4836.070232780612) - ## t2_1gph500_2 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-4836.070232780612)/(6007.097417091836-4836.070232780612) - #x_processed[:,:,:,2] = (X[:,:,:,2]-4836.070232780612)/(6007.097417091836-4836.070232780612) - - ### No standardization for moving Objects test set: Just 0s and 1s - #x_processed = np.zeros(shape=X.shape) - #x_processed = X - - ### t2_1 'standard' normalization (got one dimension less, due to just one channel) - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = X[:,:,:,1] - #x_processed[:,:,:,2] = X[:,:,:,2] - - ### t2_1 'standard' normalization (got one dimension less, due to just one channel) - x_processed = np.zeros(shape=X.shape) - x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - x_processed[:,:,:,2] = X[:,:,:,2] - - ### Standardization: (x-mean)/standard_deviation ### - #Doesn't work due to some activation functions - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-285.1751264870658)/8.770013367617763 - #x_processed[:,:,:,1] = (X[:,:,:,1]-101420.4382666807)/1071.5999818175521 - #x_processed[:,:,:,2] = (X[:,:,:,2]-5607.662795353248)/200.62593105865764 - - ### Standardization+Normalization ### - # standardize:(x-mean)/standard_deviation - #x_preprocessed = np.zeros(shape=X.shape) - #x_preprocessed[:,:,:,0] = (X[:,:,:,0]-285.1751264870658)/8.770013367617763 - #x_preprocessed[:,:,:,1] = (X[:,:,:,1]-101420.4382666807)/1071.5999818175521 - #x_preprocessed[:,:,:,2] = (X[:,:,:,2]-5607.662795353248)/200.62593105865764 - # normalize:(x-min(x))/(max(x)-min(x)) - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (x_preprocessed[:,:,:,0]-np.amin(x_preprocessed[:,:,:,0]))/(np.amax(x_preprocessed[:,:,:,0])-np.amin(x_preprocessed[:,:,:,0])) - #x_processed[:,:,:,1] = (x_preprocessed[:,:,:,1]-np.amin(x_preprocessed[:,:,:,1]))/(np.amax(x_preprocessed[:,:,:,1])-np.amin(x_preprocessed[:,:,:,1])) - #x_processed[:,:,:,2] = (x_preprocessed[:,:,:,2]-np.amin(x_preprocessed[:,:,:,2]))/(np.amax(x_preprocessed[:,:,:,2])-np.amin(x_preprocessed[:,:,:,2])) - - return x_processed.astype(np.float32) - #return X.astype(np.float32) / 255 - - def create_all(self): - X_all = np.zeros((self.N_sequences, self.nt) + self.im_shape, np.float32) - for i, idx in enumerate(self.possible_starts): - X_all[i] = self.preprocess(self.X[idx:idx+self.nt]) - return X_all diff --git a/workflow_parallel_frame_prediction/DataPostprocess/keras_utils.py b/workflow_parallel_frame_prediction/DataPostprocess/keras_utils.py deleted file mode 100755 index ededcc74..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/keras_utils.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -import numpy as np - -from keras import backend as K -from keras.legacy.interfaces import generate_legacy_interface, recurrent_args_preprocessor -from keras.models import model_from_json - -legacy_prednet_support = generate_legacy_interface( - allowed_positional_args=['stack_sizes', 'R_stack_sizes', - 'A_filt_sizes', 'Ahat_filt_sizes', 'R_filt_sizes'], - conversions=[('dim_ordering', 'data_format'), - ('consume_less', 'implementation')], - value_conversions={'dim_ordering': {'tf': 'channels_last', - 'th': 'channels_first', - 'default': None}, - 'consume_less': {'cpu': 0, - 'mem': 1, - 'gpu': 2}}, - preprocessor=recurrent_args_preprocessor) - -# Convert old Keras (1.2) json models and weights to Keras 2.0 -def convert_model_to_keras2(old_json_file, old_weights_file, new_json_file, new_weights_file): - from prednet import PredNet - # If using tensorflow, it doesn't allow you to load the old weights. - if K.backend() != 'theano': - os.environ['KERAS_BACKEND'] = backend - reload(K) - - f = open(old_json_file, 'r') - json_string = f.read() - f.close() - model = model_from_json(json_string, custom_objects = {'PredNet': PredNet}) - model.load_weights(old_weights_file) - - weights = model.layers[1].get_weights() - if weights[0].shape[0] == model.layers[1].stack_sizes[1]: - for i, w in enumerate(weights): - if w.ndim == 4: - weights[i] = np.transpose(w, (2, 3, 1, 0)) - model.set_weights(weights) - - model.save_weights(new_weights_file) - json_string = model.to_json() - with open(new_json_file, "w") as f: - f.write(json_string) - - -if __name__ == '__main__': - old_dir = './model_data/' - new_dir = './model_data_keras2/' - if not os.path.exists(new_dir): - os.mkdir(new_dir) - for w_tag in ['', '-Lall', '-extrapfinetuned']: - m_tag = '' if w_tag == '-Lall' else w_tag - convert_model_to_keras2(old_dir + 'prednet_kitti_model' + m_tag + '.json', - old_dir + 'prednet_kitti_weights' + w_tag + '.hdf5', - new_dir + 'prednet_kitti_model' + m_tag + '.json', - new_dir + 'prednet_kitti_weights' + w_tag + '.hdf5') diff --git a/workflow_parallel_frame_prediction/DataPostprocess/kitti_evaluate_parallel.py b/workflow_parallel_frame_prediction/DataPostprocess/kitti_evaluate_parallel.py deleted file mode 100755 index 1c1166ee..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/kitti_evaluate_parallel.py +++ /dev/null @@ -1,159 +0,0 @@ -''' -Evaluate trained PredNet on KITTI sequences. -Calculates mean-squared error and plots predictions. -''' -import math -import os -import numpy as np -#from six.moves import cPickle -import matplotlib -matplotlib.use('Agg') -import matplotlib.pyplot as plt -import matplotlib.gridspec as gridspec -from keras import backend as K -from keras.models import Model, model_from_json -from keras.layers import Input, Dense, Flatten -from prednet import PredNet -from data_utils import SequenceGenerator -from kitti_settings import * -##Just for checking how the shape is after generator.create_all() from Sequence Generator -#import hickle as hkl -import horovod.keras as hvd -import tensorflow as tf - -#Horovod:initialize horovod -hvd.init() -#Horovod: pin GPU to be used for process local rank (one GPU per process) -config = tf.ConfigProto() -config.gpu_options.allow_growth = True -config.gpu_options.visible_device_list = str(hvd.local_rank()) -K.set_session(tf.Session(config=config)) - -n_plot = 10 -batch_size = 5 -nt = 10 - -##Configure the horovod - -#weights_file = os.path.join(WEIGHTS_DIR, 'tensorflow_weights/prednet_kitti_weights.hdf5') -weights_file = os.path.join(WEIGHTS_DIR, 'prednet_kitti_weights.hdf5') -print("weights loaded") -json_file = os.path.join(WEIGHTS_DIR, 'prednet_kitti_model.json') -print("model loaded") -test_file = os.path.join(DATA_DIR, 'X_train.hkl') -print("test file loaded") -test_sources = os.path.join(DATA_DIR, 'sources_test.hkl') -print("test source loaded") - -# Load trained model -f = open(json_file, 'r') -json_string = f.read() -f.close() -train_model = model_from_json(json_string, custom_objects = {'PredNet': PredNet}) -train_model.load_weights(weights_file) -print("Trained model is loaded") - -# Create testing model (to output predictions) -layer_config = train_model.layers[1].get_config() -layer_config['output_mode'] = 'prediction' -data_format = layer_config['data_format'] if 'data_format' in layer_config else layer_config['dim_ordering'] -test_prednet = PredNet(weights=train_model.layers[1].get_weights(), **layer_config) -input_shape = list(train_model.layers[0].batch_input_shape[1:]) -input_shape[0] = nt -inputs = Input(shape=tuple(input_shape)) -predictions = test_prednet(inputs) -test_model = Model(inputs=inputs, outputs=predictions) - -#Bing: change the unique to all,need to ask severin why training data use all , but for testing use unique -test_generator = SequenceGenerator(test_file, test_sources, nt, sequence_start_mode='all', data_format=data_format) -print ("test_generator finished") -X_test = test_generator.create_all() -print(X_test.shape) -#Bing, replace this part with horovod because of the memeory issue -X_test_batch_size = round(X_test.shape[0]/hvd.size()) - -def post_process(rank = 0): - print ("Rank {}".format(rank)) - X_test_batch = X_test[rank * X_test_batch_size:(rank + 1) * X_test_batch_size] - print ("X_test_batch size",X_test_batch.shape) - X_hat = test_model.predict(X_test_batch, batch_size) - - if data_format == 'channels_first': - X_test_batch = np.transpose(X_test_batch, (0, 1, 3, 4, 2)) - X_hat = np.transpose(X_hat, (0, 1, 3, 4, 2)) - - ##Just for checking how the shape is after generator.create_all() from Sequence Generator - #hkl.dump(X_test, os.path.join(RESULTS_SAVE_DIR, 'X_AfterGeneratorStandardized.hkl')) - #hkl.dump(X_hat, os.path.join(RESULTS_SAVE_DIR, 'X_hatStandardized.hkl')) - # - - # Compare MSE of PredNet predictions vs. using last frame. Write results to prediction_scores.txt - # Furthermore, calculate Model MSE from the last prediction of the sequence only - # as the model improves after several frames (mse_model_last) - # Typical shape of X_test and X_hat: (263, 10, 128, 160, 3) - # where 263 are the sequences, 10 ist the amount of frames in one sequence, - # 128 & 160 are the image sice and 3 the number of layers. - # For our case only take layer 0 (= T2) into account. - shapeXhat = str(X_hat.shape) #Just have a look at the shapes to be sure we are calculating the right MSE - shapeXtest = str(X_test_batch.shape) - mse_model = np.mean((X_test_batch[:, 1:,:,:,0] - X_hat[:, 1:,:,:,0])**2) # look at all timesteps except the first - mse_model_last = np.mean((X_test_batch[:, 9,:,:,0] - X_hat[:, 9,:,:,0])**2 ) - mse_prev = np.mean((X_test_batch[:, :-1,:,:,0] - X_test_batch[:, 1:,:,:,0])**2) - - # Calculate PSNR - # Function to calculate PSNR - # In the absence of noise, the two images I and K are identical, and thus the MSE is zero. In this case the PSNR is infinite. - # Or here the best value: 100 - def psnr(img1, img2): - mse = np.mean((img1-img2) ** 2) - if mse == 0: return 100 - PIXEL_MAX = 1 - return 20 * math.log10(PIXEL_MAX/math.sqrt(mse)) - - psnr_model = psnr(X_test_batch[:, 1:,:,:,0], X_hat[:, 1:,:,:,0]) - psnr_model_last = psnr(X_test_batch[:, 9,:,:,0], X_hat[:, 9,:,:,0]) - psnr_prev = psnr(X_test_batch[:, :-1,:,:,0], X_test_batch[:, 1:,:,:,0]) - print("Evaluations are completed") - - if not os.path.exists(RESULTS_SAVE_DIR): os.mkdir(RESULTS_SAVE_DIR) - f = open(RESULTS_SAVE_DIR + '/prediction_scores_rank_{}.txt'.format(rank), 'w') - - f.write("X_test_batch_size:{} ; Rank: {}\n".format(X_test_batch_size,hvd.rank())) - f.write("Model MSE: %f\n" % mse_model) - f.write("Model MSE from only last prediction in sequence: %f\n" % mse_model_last) - f.write("Previous Frame MSE: %f\n" % mse_prev) - f.write("Model PSNR: %f\n" % psnr_model) - f.write("Model PSNR from only last prediction in sequence: %f\n" % psnr_model_last) - f.write("Previous frame PSNR: %f\n" % psnr_prev) - f.write("Shape of X_test: " + shapeXtest) - f.write("") - f.write("Shape of X_hat: " + shapeXhat) - f.close() - print("Results are saved to {}\n".format(RESULTS_SAVE_DIR + "/prediction_scores_rank_{}.txt".format(rank))) - - # Plot some predictions - aspect_ratio = float(X_hat.shape[2]) / X_hat.shape[3] - plt.figure(figsize = (nt, 2*aspect_ratio)) - gs = gridspec.GridSpec(2, nt) - gs.update(wspace=0., hspace=0.) - plot_save_dir = os.path.join(RESULTS_SAVE_DIR, 'prediction_plots_rank_{}/'.format(rank)) - if not os.path.exists(plot_save_dir): os.mkdir(plot_save_dir) - plot_idx = np.random.permutation(X_test_batch.shape[0])[:n_plot] - for i in plot_idx: - for t in range(nt): - plt.subplot(gs[t]) - plt.imshow(X_test_batch[i,t,:,:,0], interpolation='none') #the last index sets the channel. 0 = t2 - #plt.pcolormesh(X_test[i,t,::-1,:,0], shading='bottom', cmap=plt.cm.jet) - plt.tick_params(axis='both', which='both', bottom=False, top=False, left=False, right=False, labelbottom=False, labelleft=False) - if t==0: plt.ylabel('Actual', fontsize=10) - - plt.subplot(gs[t + nt]) - plt.imshow(X_hat[i,t,:,:,0], interpolation='none') - #plt.pcolormesh(X_hat[i,t,::-1,:,0], shading='bottom', cmap=plt.cm.jet) - plt.tick_params(axis='both', which='both', bottom=False, top=False, left=False, right=False, labelbottom=False, labelleft=False) - if t==0: plt.ylabel('Predicted', fontsize=10) - plt.savefig(plot_save_dir + 'plot_' + str(i) + '.png') - plt.clf() - - -post_process(rank = hvd.rank()) \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/DataPostprocess/kitti_settings.py b/workflow_parallel_frame_prediction/DataPostprocess/kitti_settings.py deleted file mode 100755 index 489989ee..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/kitti_settings.py +++ /dev/null @@ -1,19 +0,0 @@ -# Where KITTI data will be saved if you run process_kitti.py -# If you directly download the processed data, change to the path of the data. -## Changed logic: Now this is the path where the processed data lies: X_train,val,test -#DATA_DIR = './kitti_data/' -#data directory for training data 2015 and 2016 -#DATA_DIR = '/p/project/cjjsc42/severin/try3' -#data directory for moving objects: -#DATA_DIR = '/p/home/jusers/hussmann1/jureca/movingObjects/se_nw' -#data directory for featuretesting: -##DATA_DIR = './testTry2' -DATA_DIR = '/p/scratch/cjjsc42/bing/pystager-development/processData/splits' -# Where model weights and config will be saved if you run kitti_train.py -# If you directly download the trained weights, change to appropriate path. -WEIGHTS_DIR = '/p/project/cjjsc42/bing/ml-severin/model_data_keras2' -#WEIGHTS_DIR = '/p/project/cjjsc42/bing/ml-severin/model_data_keras2' - -# Where results (prediction plots and evaluation file) will be saved. -RESULTS_SAVE_DIR = '/p/project/cjjsc42/bing/ml-severin/kitti_results' - diff --git a/workflow_parallel_frame_prediction/DataPostprocess/packageInstallation.sh b/workflow_parallel_frame_prediction/DataPostprocess/packageInstallation.sh deleted file mode 100644 index 1039e5fd..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/packageInstallation.sh +++ /dev/null @@ -1,9 +0,0 @@ -module --force purge -module /usr/local/software/jureca/OtherStages -module load Stages/2019a -module load Intel/2019.3.199-GCC-8.3.0 ParaStationMPI/5.2.2-1-mt -module load mpi4py/3.0.1-Python-3.6.8 -pip3 install --user netCDF4 -pip3 install --user numpy - - diff --git a/workflow_parallel_frame_prediction/DataPostprocess/parameters_kitti_evaluate.dat b/workflow_parallel_frame_prediction/DataPostprocess/parameters_kitti_evaluate.dat deleted file mode 100755 index ac64b704..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/parameters_kitti_evaluate.dat +++ /dev/null @@ -1,14 +0,0 @@ -import os - -# ============ input parameters =================== # -# 0:deactivate 1: active - -Pleas fill the following parameters list for PyStager -Source_Directory = /p/fastdata/slmet/slmet111/met_data/ecmwf/era5/nc/2017/ -Destination_Directory = /p/scratch/cjjsc42/bing/pystager-development/tryData/ -Log_Directory = /p/project/cjjsc42/bing/pystager-development/log -Rsync_Status = 1 -Checksum_Status = 0 - - - diff --git a/workflow_parallel_frame_prediction/DataPostprocess/prednet.py b/workflow_parallel_frame_prediction/DataPostprocess/prednet.py deleted file mode 100755 index b5a0208a..00000000 --- a/workflow_parallel_frame_prediction/DataPostprocess/prednet.py +++ /dev/null @@ -1,311 +0,0 @@ -import numpy as np - -from keras import backend as K -from keras import activations -from keras.layers import Recurrent -from keras.layers import Conv2D, UpSampling2D, MaxPooling2D -from keras.engine import InputSpec -from keras_utils import legacy_prednet_support - -class PredNet(Recurrent): - '''PredNet architecture - Lotter 2016. - Stacked convolutional LSTM inspired by predictive coding principles. - - # Arguments - stack_sizes: number of channels in targets (A) and predictions (Ahat) in each layer of the architecture. - Length is the number of layers in the architecture. - First element is the number of channels in the input. - Ex. (3, 16, 32) would correspond to a 3 layer architecture that takes in RGB images and has 16 and 32 - channels in the second and third layers, respectively. - R_stack_sizes: number of channels in the representation (R) modules. - Length must equal length of stack_sizes, but the number of channels per layer can be different. - A_filt_sizes: filter sizes for the target (A) modules. - Has length of 1 - len(stack_sizes). - Ex. (3, 3) would mean that targets for layers 2 and 3 are computed by a 3x3 convolution of the errors (E) - from the layer below (followed by max-pooling) - Ahat_filt_sizes: filter sizes for the prediction (Ahat) modules. - Has length equal to length of stack_sizes. - Ex. (3, 3, 3) would mean that the predictions for each layer are computed by a 3x3 convolution of the - representation (R) modules at each layer. - R_filt_sizes: filter sizes for the representation (R) modules. - Has length equal to length of stack_sizes. - Corresponds to the filter sizes for all convolutions in the LSTM. - pixel_max: the maximum pixel value. - Used to clip the pixel-layer prediction. - error_activation: activation function for the error (E) units. - A_activation: activation function for the target (A) and prediction (A_hat) units. - LSTM_activation: activation function for the cell and hidden states of the LSTM. - LSTM_inner_activation: activation function for the gates in the LSTM. - output_mode: either 'error', 'prediction', 'all' or layer specification (ex. R2, see below). - Controls what is outputted by the PredNet. - If 'error', the mean response of the error (E) units of each layer will be outputted. - That is, the output shape will be (batch_size, nb_layers). - If 'prediction', the frame prediction will be outputted. - If 'all', the output will be the frame prediction concatenated with the mean layer errors. - The frame prediction is flattened before concatenation. - Nomenclature of 'all' is kept for backwards compatibility, but should not be confused with returning all of the layers of the model - For returning the features of a particular layer, output_mode should be of the form unit_type + layer_number. - For instance, to return the features of the LSTM "representational" units in the lowest layer, output_mode should be specificied as 'R0'. - The possible unit types are 'R', 'Ahat', 'A', and 'E' corresponding to the 'representation', 'prediction', 'target', and 'error' units respectively. - extrap_start_time: time step for which model will start extrapolating. - Starting at this time step, the prediction from the previous time step will be treated as the "actual" - data_format: 'channels_first' or 'channels_last'. - It defaults to the `image_data_format` value found in your - Keras config file at `~/.keras/keras.json`. - - # References - - [Deep predictive coding networks for video prediction and unsupervised learning](https://arxiv.org/abs/1605.08104) - - [Long short-term memory](http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf) - - [Convolutional LSTM network: a machine learning approach for precipitation nowcasting](http://arxiv.org/abs/1506.04214) - - [Predictive coding in the visual cortex: a functional interpretation of some extra-classical receptive-field effects](http://www.nature.com/neuro/journal/v2/n1/pdf/nn0199_79.pdf) - ''' - @legacy_prednet_support - def __init__(self, stack_sizes, R_stack_sizes, - A_filt_sizes, Ahat_filt_sizes, R_filt_sizes, - pixel_max=1., error_activation='relu', A_activation='relu', - LSTM_activation='tanh', LSTM_inner_activation='hard_sigmoid', - output_mode='error', extrap_start_time=None, - data_format=K.image_data_format(), **kwargs): - self.stack_sizes = stack_sizes - self.nb_layers = len(stack_sizes) - assert len(R_stack_sizes) == self.nb_layers, 'len(R_stack_sizes) must equal len(stack_sizes)' - self.R_stack_sizes = R_stack_sizes - assert len(A_filt_sizes) == (self.nb_layers - 1), 'len(A_filt_sizes) must equal len(stack_sizes) - 1' - self.A_filt_sizes = A_filt_sizes - assert len(Ahat_filt_sizes) == self.nb_layers, 'len(Ahat_filt_sizes) must equal len(stack_sizes)' - self.Ahat_filt_sizes = Ahat_filt_sizes - assert len(R_filt_sizes) == (self.nb_layers), 'len(R_filt_sizes) must equal len(stack_sizes)' - self.R_filt_sizes = R_filt_sizes - - self.pixel_max = pixel_max - self.error_activation = activations.get(error_activation) - self.A_activation = activations.get(A_activation) - self.LSTM_activation = activations.get(LSTM_activation) - self.LSTM_inner_activation = activations.get(LSTM_inner_activation) - - default_output_modes = ['prediction', 'error', 'all'] - layer_output_modes = [layer + str(n) for n in range(self.nb_layers) for layer in ['R', 'E', 'A', 'Ahat']] - assert output_mode in default_output_modes + layer_output_modes, 'Invalid output_mode: ' + str(output_mode) - self.output_mode = output_mode - if self.output_mode in layer_output_modes: - self.output_layer_type = self.output_mode[:-1] - self.output_layer_num = int(self.output_mode[-1]) - else: - self.output_layer_type = None - self.output_layer_num = None - self.extrap_start_time = extrap_start_time - - assert data_format in {'channels_last', 'channels_first'}, 'data_format must be in {channels_last, channels_first}' - self.data_format = data_format - self.channel_axis = -3 if data_format == 'channels_first' else -1 - self.row_axis = -2 if data_format == 'channels_first' else -3 - self.column_axis = -1 if data_format == 'channels_first' else -2 - super(PredNet, self).__init__(**kwargs) - self.input_spec = [InputSpec(ndim=5)] - - def compute_output_shape(self, input_shape): - if self.output_mode == 'prediction': - out_shape = input_shape[2:] - elif self.output_mode == 'error': - out_shape = (self.nb_layers,) - elif self.output_mode == 'all': - out_shape = (np.prod(input_shape[2:]) + self.nb_layers,) - else: - stack_str = 'R_stack_sizes' if self.output_layer_type == 'R' else 'stack_sizes' - stack_mult = 2 if self.output_layer_type == 'E' else 1 - out_stack_size = stack_mult * getattr(self, stack_str)[self.output_layer_num] - out_nb_row = input_shape[self.row_axis] / 2**self.output_layer_num - out_nb_col = input_shape[self.column_axis] / 2**self.output_layer_num - if self.data_format == 'channels_first': - out_shape = (out_stack_size, out_nb_row, out_nb_col) - else: - out_shape = (out_nb_row, out_nb_col, out_stack_size) - - if self.return_sequences: - return (input_shape[0], input_shape[1]) + out_shape - else: - return (input_shape[0],) + out_shape - - def get_initial_state(self, x): - input_shape = self.input_spec[0].shape - init_nb_row = input_shape[self.row_axis] - init_nb_col = input_shape[self.column_axis] - - base_initial_state = K.zeros_like(x) # (samples, timesteps) + image_shape - non_channel_axis = -1 if self.data_format == 'channels_first' else -2 - for _ in range(2): - base_initial_state = K.sum(base_initial_state, axis=non_channel_axis) - base_initial_state = K.sum(base_initial_state, axis=1) # (samples, nb_channels) - - initial_states = [] - states_to_pass = ['r', 'c', 'e'] - nlayers_to_pass = {u: self.nb_layers for u in states_to_pass} - if self.extrap_start_time is not None: - states_to_pass.append('ahat') # pass prediction in states so can use as actual for t+1 when extrapolating - nlayers_to_pass['ahat'] = 1 - for u in states_to_pass: - for l in range(nlayers_to_pass[u]): - ds_factor = 2 ** l - nb_row = init_nb_row // ds_factor - nb_col = init_nb_col // ds_factor - if u in ['r', 'c']: - stack_size = self.R_stack_sizes[l] - elif u == 'e': - stack_size = 2 * self.stack_sizes[l] - elif u == 'ahat': - stack_size = self.stack_sizes[l] - output_size = stack_size * nb_row * nb_col # flattened size - - reducer = K.zeros((input_shape[self.channel_axis], output_size)) # (nb_channels, output_size) - initial_state = K.dot(base_initial_state, reducer) # (samples, output_size) - if self.data_format == 'channels_first': - output_shp = (-1, stack_size, nb_row, nb_col) - else: - output_shp = (-1, nb_row, nb_col, stack_size) - initial_state = K.reshape(initial_state, output_shp) - initial_states += [initial_state] - - if K._BACKEND == 'theano': - from theano import tensor as T - # There is a known issue in the Theano scan op when dealing with inputs whose shape is 1 along a dimension. - # In our case, this is a problem when training on grayscale images, and the below line fixes it. - initial_states = [T.unbroadcast(init_state, 0, 1) for init_state in initial_states] - - if self.extrap_start_time is not None: - initial_states += [K.variable(0, int if K.backend() != 'tensorflow' else 'int32')] # the last state will correspond to the current timestep - return initial_states - - def build(self, input_shape): - self.input_spec = [InputSpec(shape=input_shape)] - self.conv_layers = {c: [] for c in ['i', 'f', 'c', 'o', 'a', 'ahat']} - - for l in range(self.nb_layers): - for c in ['i', 'f', 'c', 'o']: - act = self.LSTM_activation if c == 'c' else self.LSTM_inner_activation - self.conv_layers[c].append(Conv2D(self.R_stack_sizes[l], self.R_filt_sizes[l], padding='same', activation=act, data_format=self.data_format)) - - act = 'relu' if l == 0 else self.A_activation - self.conv_layers['ahat'].append(Conv2D(self.stack_sizes[l], self.Ahat_filt_sizes[l], padding='same', activation=act, data_format=self.data_format)) - - if l < self.nb_layers - 1: - self.conv_layers['a'].append(Conv2D(self.stack_sizes[l+1], self.A_filt_sizes[l], padding='same', activation=self.A_activation, data_format=self.data_format)) - - self.upsample = UpSampling2D(data_format=self.data_format) - self.pool = MaxPooling2D(data_format=self.data_format) - - self.trainable_weights = [] - nb_row, nb_col = (input_shape[-2], input_shape[-1]) if self.data_format == 'channels_first' else (input_shape[-3], input_shape[-2]) - for c in sorted(self.conv_layers.keys()): - for l in range(len(self.conv_layers[c])): - ds_factor = 2 ** l - if c == 'ahat': - nb_channels = self.R_stack_sizes[l] - elif c == 'a': - nb_channels = 2 * self.stack_sizes[l] - else: - nb_channels = self.stack_sizes[l] * 2 + self.R_stack_sizes[l] - if l < self.nb_layers - 1: - nb_channels += self.R_stack_sizes[l+1] - in_shape = (input_shape[0], nb_channels, nb_row // ds_factor, nb_col // ds_factor) - if self.data_format == 'channels_last': in_shape = (in_shape[0], in_shape[2], in_shape[3], in_shape[1]) - with K.name_scope('layer_' + c + '_' + str(l)): - self.conv_layers[c][l].build(in_shape) - self.trainable_weights += self.conv_layers[c][l].trainable_weights - - self.states = [None] * self.nb_layers*3 - - if self.extrap_start_time is not None: - self.t_extrap = K.variable(self.extrap_start_time, int if K.backend() != 'tensorflow' else 'int32') - self.states += [None] * 2 # [previous frame prediction, timestep] - - def step(self, a, states): - r_tm1 = states[:self.nb_layers] - c_tm1 = states[self.nb_layers:2*self.nb_layers] - e_tm1 = states[2*self.nb_layers:3*self.nb_layers] - - if self.extrap_start_time is not None: - t = states[-1] - a = K.switch(t >= self.t_extrap, states[-2], a) # if past self.extrap_start_time, the previous prediction will be treated as the actual - - c = [] - r = [] - e = [] - - # Update R units starting from the top - for l in reversed(range(self.nb_layers)): - inputs = [r_tm1[l], e_tm1[l]] - if l < self.nb_layers - 1: - inputs.append(r_up) - - inputs = K.concatenate(inputs, axis=self.channel_axis) - i = self.conv_layers['i'][l].call(inputs) - f = self.conv_layers['f'][l].call(inputs) - o = self.conv_layers['o'][l].call(inputs) - _c = f * c_tm1[l] + i * self.conv_layers['c'][l].call(inputs) - _r = o * self.LSTM_activation(_c) - c.insert(0, _c) - r.insert(0, _r) - - if l > 0: - r_up = self.upsample.call(_r) - - # Update feedforward path starting from the bottom - for l in range(self.nb_layers): - ahat = self.conv_layers['ahat'][l].call(r[l]) - if l == 0: - ahat = K.minimum(ahat, self.pixel_max) - frame_prediction = ahat - - # compute errors - e_up = self.error_activation(ahat - a) - e_down = self.error_activation(a - ahat) - - e.append(K.concatenate((e_up, e_down), axis=self.channel_axis)) - - if self.output_layer_num == l: - if self.output_layer_type == 'A': - output = a - elif self.output_layer_type == 'Ahat': - output = ahat - elif self.output_layer_type == 'R': - output = r[l] - elif self.output_layer_type == 'E': - output = e[l] - - if l < self.nb_layers - 1: - a = self.conv_layers['a'][l].call(e[l]) - a = self.pool.call(a) # target for next layer - - if self.output_layer_type is None: - if self.output_mode == 'prediction': - output = frame_prediction - else: - for l in range(self.nb_layers): - layer_error = K.mean(K.batch_flatten(e[l]), axis=-1, keepdims=True) - all_error = layer_error if l == 0 else K.concatenate((all_error, layer_error), axis=-1) - if self.output_mode == 'error': - output = all_error - else: - output = K.concatenate((K.batch_flatten(frame_prediction), all_error), axis=-1) - - states = r + c + e - if self.extrap_start_time is not None: - states += [frame_prediction, t + 1] - return output, states - - def get_config(self): - config = {'stack_sizes': self.stack_sizes, - 'R_stack_sizes': self.R_stack_sizes, - 'A_filt_sizes': self.A_filt_sizes, - 'Ahat_filt_sizes': self.Ahat_filt_sizes, - 'R_filt_sizes': self.R_filt_sizes, - 'pixel_max': self.pixel_max, - 'error_activation': self.error_activation.__name__, - 'A_activation': self.A_activation.__name__, - 'LSTM_activation': self.LSTM_activation.__name__, - 'LSTM_inner_activation': self.LSTM_inner_activation.__name__, - 'data_format': self.data_format, - 'extrap_start_time': self.extrap_start_time, - 'output_mode': self.output_mode} - base_config = super(PredNet, self).get_config() - return dict(list(base_config.items()) + list(config.items())) diff --git a/workflow_parallel_frame_prediction/DataPreprocess/Stager_devel_N_24_process_netCDF.sh b/workflow_parallel_frame_prediction/DataPreprocess/Stager_devel_N_24_process_netCDF.sh deleted file mode 100755 index 98333610..00000000 --- a/workflow_parallel_frame_prediction/DataPreprocess/Stager_devel_N_24_process_netCDF.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -x -#SBATCH --account=deepacf -#SBATCH --nodes=1 -#SBATCH --ntasks=12 -##SBATCH --ntasks-per-node=12 -#SBATCH --cpus-per-task=1 -#SBATCH --output=process_netcdf-out.%j -#SBATCH --error=process_netcdf-err.%j -#SBATCH --time=00:20:00 -#SBATCH --partition=devel -#SBATCH --mail-type=ALL -#SBATCH --mail-user=b.gong@fz-juelich.de - -module --force purge -module use $OTHERSTAGES -module load Stages/2019a -module load Intel/2019.3.199-GCC-8.3.0 ParaStationMPI/5.2.2-1 -module load h5py/2.9.0-Python-3.6.8 -module load mpi4py/3.0.1-Python-3.6.8 - -srun python mpi_stager_v2_process_netCDF.py --source_dir /p/scratch/deepacf/video_prediction_shared_folder/extractedData/\ ---destination_dir /p/scratch/deepacf/bing/processData_size_64_64_3_3t_norm_test2 diff --git a/workflow_parallel_frame_prediction/DataPreprocess/external_function.py b/workflow_parallel_frame_prediction/DataPreprocess/external_function.py deleted file mode 100755 index c360c0e0..00000000 --- a/workflow_parallel_frame_prediction/DataPreprocess/external_function.py +++ /dev/null @@ -1,158 +0,0 @@ -#from mpi4py import MPI -from os import walk -import os -import sys -import subprocess -import logging -import time -import hashlib - -# ======================= List of functions ====================================== # - -# check the rank and print it - -def logger(file_name, logger_level, program_name): - # Log file starter - - logging.basicConfig(filename=file_name, level=logger_level, - format='%(asctime)s:%(levelname)s:%(message)s') - logging.debug(' === PyStager is started === ') - print(str(program_name) + ' is Running .... ') - - -def config_file(config_file_name): - params = {} - for line in open(config_file_name): - line = line.strip() - read_in_value = line.split("=") - if len(read_in_value) == 2: - params[read_in_value[0].strip()] = read_in_value[1].strip() - - source_dir = str(params["Source_Directory"]) - print(source_dir) - destination_dir = str(params["Destination_Directory"]) - log_dir = str(params["Log_Directory"]) - rsync_status = int(params["Rsync_Status"]) - return source_dir, destination_dir, log_dir, rsync_status - - -def directory_scanner(source_path): - # Take a look inside a directories and make a list of ll the folders, sub directories, number of the files and size - # NOTE : It will neglect if there is a sub-directories inside directories!!! - - dir_detail_list = [] # directories details - sub_dir_list = [] - total_size_source = 0 - total_num_files = 0 - list_directories = [] - - list_directories = os.listdir(source_path) - print(list_directories) - print(int(len(list_directories))) - - for d in list_directories: - print(d) - path = source_path + d - print(path) - if os.path.isdir(path): - sub_dir_list.append(d) - sub_dir_list.sort() - num_files = 0 - # size of the files and subdirectories - size_dir = subprocess.check_output(['du', '-sc', path]) - splitted = size_dir.split() # fist item is the size of the folder - size = (splitted[0]) - num_files = len([f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]) - dir_detail_list.extend([d, size, num_files]) - total_num_files = total_num_files + int(num_files) - total_size_source = total_size_source + int(size) - else: - print(path, 'does not exist') - print("===== Debug here =====") - - total_num_directories = int(len(list_directories)) - total_size_source = float(total_size_source / 1000000) - - message = 'Total size of the source directory is:' + str(total_size_source) + 'Gb.' - print(message) - message = "Total number of the files in the source directory is: " + str(total_num_files) - print(message) - message = "Total number of the directories in the source directory is: " + str(total_num_directories) - print(message) - - return dir_detail_list, sub_dir_list, total_size_source, total_num_files, total_num_directories - - -def load_distributor(dir_detail_list, sub_dir_list, total_size_source, total_num_files, total_num_directories, p): - # create a dictionary with p number of keys - # for each directory they add the name to one of the keys - transfer_dict = dict.fromkeys(list(range(1, p))) - print(transfer_dict) - # package_counter = 0 possibility to use the counter to fill - counter = 1 - for Directory_counter in range(0, total_num_directories): - - if transfer_dict[counter] is None: # if the value for the key is None add to it - transfer_dict[counter] = sub_dir_list[Directory_counter] - else: # if key has a value join the new value to the old value - transfer_dict[counter] = "{};{}".format(transfer_dict[counter], sub_dir_list[Directory_counter]) - counter = counter + 1 - if counter == p: - counter = 1 - - return transfer_dict - -def sync_file(source_path, destination_dir, job_name, rsync_status): - rsync_msg = ("rsync -r " + source_path + job_name + "/" + " " + destination_dir + "/" + job_name) - # print('Node:', str(my_rank),'will execute :', rsync_str,'\r\n') - # sync the assigned folder - - if rsync_status == 1: - os.system(rsync_msg) - - - -def hash_directory(source_path,job_name,hash_rep_file,input_status): - #sha256_hash = hashlib.sha256() - md5_hash = hashlib.md5() - - ########## Create a hashed file repasitory for direcotry(ies) assigned to node ####### - hash_repo_text = input_status + "_"+job_name +"_hashed.txt" - os.chdir(hash_rep_file) - hashed_text_note=open(hash_repo_text,"w+") - - # job_name is the name of the subdirectory that is going to be processed - directory_to_process = source_path + job_name - # print(directory_to_process) - files_list = [] - for dirpath, dirnames, filenames in os.walk(directory_to_process): - files_list.extend(filenames) - - os.chdir(directory_to_process) # change to the working directory - - for file_to_process in filenames: - - ## ======= this is the sha256 checksum ========= # - #with open(file_to_process,"rb") as f: - # # Read and update hash in chunks of 4K - # for byte_block in iter(lambda: f.read(4096),b""): - # sha256_hash.update(byte_block) - # hashed_file = sha256_hash.hexdigest() - - with open(file_to_process,"rb") as f: - # Read and update hash in chunks of 4K - for byte_block in iter(lambda: f.read(4096),b""): - md5_hash.update(byte_block) - hashed_file = md5_hash.hexdigest() - - hashed_text_note.write(hashed_file) - - return - -def md5(fname): - md5_hash = hashlib.md5() - with open(fname,"rb") as f: - # Read and update hash in chunks of 4K - for byte_block in iter(lambda: f.read(4096),b""): - md5_hash.update(byte_block) - return md5_hash.hexdigest() diff --git a/workflow_parallel_frame_prediction/DataPreprocess/mpi_split_data_multi_years.py b/workflow_parallel_frame_prediction/DataPreprocess/mpi_split_data_multi_years.py deleted file mode 100644 index 68d1ddfb..00000000 --- a/workflow_parallel_frame_prediction/DataPreprocess/mpi_split_data_multi_years.py +++ /dev/null @@ -1,58 +0,0 @@ -from mpi4py import MPI -import argparse -from process_netCDF_v2 import * -from metadata import MetaData -import json - -#add parser arguments -parser = argparse.ArgumentParser() -#parser.add_argument("--source_dir", type=str, default="/p/scratch/deepacf/bing/extractedData/") -parser.add_argument("--destination_dir","-dest",dest="destination_dir",type=str, default="/p/scratch/deepacf/bing/processData_size_64_64_3_3t_norm") -parser.add_argument("--varnames","-vars",dest="varnames", nargs = '+') -#parser.add_argument("--partition","-part",dest="partition",type=json.loads) -# help="--partition allows to control the splitting of the processed data in training, test and validation data. Pass a dictionary-like string.") - -args = parser.parse_args() -# ML 2020/06/08: Dirty workaround as long as data-splitting is done with this seperate Python-script -# called from the same parent Shell-/Batch-script as 'mpi_stager_v2_process_netCDF.py' -target_dir = os.path.join(MetaData.get_destdir_jsontmp(),"hickle") -varnames = args.varnames - -#partition = args.partition -#all_keys = partition.keys() -#for key in all_keys: -# print(partition[key]) - -cv ={} -partition1 = { - "train":{ - #"2222":[1,2,3,5,6,7,8,9,10,11,12], - #"2010_1":[1,2,3,4,5,6,7,8,9,10,11,12], - #"2012":[1,2,3,4,5,6,7,8,9,10,11,12], - #"2013_complete":[1,2,3,4,5,6,7,8,9,10,11,12], - #"2015":[1,2,3,4,5,6,7,8,9,10,11,12], - #"2017":[1,2,3,4,5,6,7,8,9,10,11,12] - "2015":[1,2,3,4,5,6,7,8,9,10,11,12] - }, - "val": - {"2016":[1,2,3,4,5,6,7,8,9,10,11,12] - }, - "test": - {"2017":[1,2,3,4,5,6,7,8,9,10,11,12] - } - } - - - - - -#cv["1"] = partition1 -#cv2["2"] = partition2 -# ini. MPI -comm = MPI.COMM_WORLD -my_rank = comm.Get_rank() # rank of the node -p = comm.Get_size() # number of assigned nods -if my_rank == 0: # node is master - split_data_multiple_years(target_dir=target_dir,partition=partition1,varnames=varnames) -else: - pass diff --git a/workflow_parallel_frame_prediction/README.md b/workflow_parallel_frame_prediction/README.md deleted file mode 100755 index 434e591f..00000000 --- a/workflow_parallel_frame_prediction/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Workflow for Frame Prediction by Parallel Deep Learning - - - -## Workflow for parallel deep learning - -This project implements a workflow for parallel deep learning to predict the 2m temperature based on Severin's master thesis [code link](https://github.com/severin1992/airtemprednet) [thesis link](https://b2drop.eudat.eu/s/RmTd8K3pLsDMFw6) . - - -The workflow consists of a sqeuence of steps (Data Extraction, Data Preprocessing, Training and Data Postprocess)to implement video prediction, and In each step try to Parallel for accelerating the whole prediction process. - - -The wokflow have been tested on the supercomputers from JSC, [JURECA](https://www.fz-juelich.de/ias/jsc/EN/Expertise/Supercomputers/JURECA/JURECA_node.html) and [JUWELS](https://www.fz-juelich.de/ias/jsc/EN/Expertise/Supercomputers/JUWELS/JUWELS_node.html) - - -## Requirement: -* Keras -* Horovod -* Python3.6 -* mpi4py - - - -## Usage - -1. Clone or download this repository, -2. Install the required modules/packages on JURECA/JUWELS. - - ```shell - source packageInstallation.sh - ``` - - Add package directory to 'PYTHONPATH' - ```shell - export PYTHONPATH=/p/home/jusers/USERNAME/jureca/.local/lib/python3.6/site-packages:$PYTHONPATH - ``` - - - ```shell - source packageInstallation.sh - ``` - Add the packages directory to the PYTHONPATH - ```shell - export PATHONPATH=/p/home/jusers/USERNAME/jureca/.local/lib/python3.6/site-packages:$PYTHONPATH - ``` - -3. Configure your input directory, output and log directory in .dat file for each step. - - -4. Run .sh file for submitting job - - -## Workflow example - - - diff --git a/workflow_parallel_frame_prediction/Training/data_utils.py b/workflow_parallel_frame_prediction/Training/data_utils.py deleted file mode 100755 index d048236f..00000000 --- a/workflow_parallel_frame_prediction/Training/data_utils.py +++ /dev/null @@ -1,163 +0,0 @@ -import hickle as hkl -import numpy as np -from keras import backend as K -from keras.preprocessing.image import Iterator - - -import inspect -print(inspect.getmembers(hkl,predicate=inspect.ismethod)) - -# Data generator that creates sequences for input into PredNet. -class SequenceGenerator(Iterator): - def __init__(self, data_file, source_file, nt, - batch_size=8, shuffle=False, seed=None, - output_mode='error', sequence_start_mode='all', N_seq=None, - data_format=K.image_data_format()): - self.X = hkl.load(data_file) # X will be like (n_images, nb_cols, nb_rows, nb_channels) - self.sources = hkl.load(source_file) # source for each image so when creating sequences can assure that consecutive frames are from same video - self.nt = nt - self.batch_size = batch_size - self.data_format = data_format - assert sequence_start_mode in {'all', 'unique'}, 'sequence_start_mode must be in {all, unique}' - self.sequence_start_mode = sequence_start_mode - assert output_mode in {'error', 'prediction'}, 'output_mode must be in {error, prediction}' - self.output_mode = output_mode - - if self.data_format == 'channels_first': - self.X = np.transpose(self.X, (0, 3, 1, 2)) - self.im_shape = self.X[0].shape - if self.sequence_start_mode == 'all': # allow for any possible sequence, starting from any frame - #bing - #self.possible_starts = np.array([i for i in range(self.X.shape[0] - self.nt) if self.sources[i] == self.sources[i + self.nt - 1]]) - self.possible_starts = np.array([i for i in range(self.X.shape[0] - self.nt)]) - elif self.sequence_start_mode == 'unique': #create sequences where each unique frame is in at most one sequence - curr_location = 0 - possible_starts = [] - while curr_location < self.X.shape[0] - self.nt + 1: - if self.sources[curr_location] == self.sources[curr_location + self.nt - 1]: - possible_starts.append(curr_location) - curr_location += self.nt - else: - curr_location += 1 - self.possible_starts = possible_starts - - if shuffle: - self.possible_starts = np.random.permutation(self.possible_starts) - if N_seq is not None and len(self.possible_starts) > N_seq: # select a subset of sequences if want to - self.possible_starts = self.possible_starts[:N_seq] - self.N_sequences = len(self.possible_starts) - print("N_sequences",self.N_sequences) - super(SequenceGenerator, self).__init__(len(self.possible_starts), batch_size, shuffle, seed) - - def __getitem__(self, null): - return self.next() - - def next(self): - with self.lock: - current_index = (self.batch_index * self.batch_size) % self.n - index_array, current_batch_size = next(self.index_generator), self.batch_size - batch_x = np.zeros((current_batch_size, self.nt) + self.im_shape, np.float32) - for i, idx in enumerate(index_array): - idx = self.possible_starts[idx] - batch_x[i] = self.preprocess(self.X[idx:idx+self.nt]) - if self.output_mode == 'error': # model outputs errors, so y should be zeros - batch_y = np.zeros(current_batch_size, np.float32) - elif self.output_mode == 'prediction': # output actual pixels - batch_y = batch_x - return batch_x, batch_y - - def preprocess(self, X): - ### Normalization after extrema cut off: ### - #cut maxs & mins to mean+3*std & mean-3*std of training set for each parameter - #x_cut = np.zeros(shape=X.shape) - #x_cut = X*1 #pass X by value and not by reference - #x_cut[:,:,:,0][X[:,:,:,0]>311.5]=311.5 #set T2 upper limit - #x_cut[:,:,:,0][X[:,:,:,0]<258.9]=258.9 #set T2 lower limit - #x_cut[:,:,:,1][X[:,:,:,1]>104635.2]=104635.2 #set GP upper limit - #x_cut[:,:,:,1][X[:,:,:,1]<98205.6]=98205.6 #set GP lower limit ###Caution: Drastical cut ### - #x_cut[:,:,:,2][X[:,:,:,2]>6209.5]=6209.5 #set GPH upper limit ###Caution: Unnecessary as it succeeds max GPH ### - #x_cut[:,:,:,2][X[:,:,:,2]<5005.8]=5005.8 #set GPH lower limit - #normalize X based on max and min values(equals upper and lower limits except highCutGPH) - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (x_cut[:,:,:,0]-258.9)/(311.5-258.9) - #x_processed[:,:,:,1] = (x_cut[:,:,:,1]-98205.6)/(104635.2-98205.6) - #x_processed[:,:,:,2] = (x_cut[:,:,:,2]-5005.8)/(6007.097417091836-5005.8) #GPH max stays; see above - - ### 'Standard' normalization: (x-min(x))/(max(x)-min(x)) ### - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-93401.125)/(105391.4375-93401.125) - #x_processed[:,:,:,2] = (X[:,:,:,2]-4836.070232780612)/(6007.097417091836-4836.070232780612) - - ### t2only 'Standard' normalization: (x-min(x))/(max(x)-min(x)) ### - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,2] = (X[:,:,:,2]-235.2141571044922)/(321.46630859375-235.2141571044922) - - ### t2_2MSL_1 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,2] = (X[:,:,:,2]-93401.125)/(105391.4375-93401.125) - - ### t2_1MSL_2 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-93401.125)/(105391.4375-93401.125) - #x_processed[:,:,:,2] = (X[:,:,:,2]-93401.125)/(105391.4375-93401.125) - - ### t2_2gph500_1 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,2] = (X[:,:,:,2]-4836.070232780612)/(6007.097417091836-4836.070232780612) - ## t2_1gph500_2 'standard' normalization: - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = (X[:,:,:,1]-4836.070232780612)/(6007.097417091836-4836.070232780612) - #x_processed[:,:,:,2] = (X[:,:,:,2]-4836.070232780612)/(6007.097417091836-4836.070232780612) - - ### No standardization for moving Objects test set: Just 0s and 1s - #x_processed = np.zeros(shape=X.shape) - #x_processed = X - - ### t2_1 'standard' normalization (got one dimension less, due to just one channel) - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - #x_processed[:,:,:,1] = X[:,:,:,1] - #x_processed[:,:,:,2] = X[:,:,:,2] - - ### t2_1 'standard' normalization (got one dimension less, due to just one channel) - x_processed = np.zeros(shape=X.shape) - x_processed[:,:,:,0] = (X[:,:,:,0]-235.2141571044922)/(321.46630859375-235.2141571044922) - x_processed[:,:,:,1] = (X[:,:,:,1]-235.2141571044922)/(321.46630859375-235.2141571044922) - x_processed[:,:,:,2] = X[:,:,:,2] - - ### Standardization: (x-mean)/standard_deviation ### - #Doesn't work due to some activation functions - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (X[:,:,:,0]-285.1751264870658)/8.770013367617763 - #x_processed[:,:,:,1] = (X[:,:,:,1]-101420.4382666807)/1071.5999818175521 - #x_processed[:,:,:,2] = (X[:,:,:,2]-5607.662795353248)/200.62593105865764 - - ### Standardization+Normalization ### - # standardize:(x-mean)/standard_deviation - #x_preprocessed = np.zeros(shape=X.shape) - #x_preprocessed[:,:,:,0] = (X[:,:,:,0]-285.1751264870658)/8.770013367617763 - #x_preprocessed[:,:,:,1] = (X[:,:,:,1]-101420.4382666807)/1071.5999818175521 - #x_preprocessed[:,:,:,2] = (X[:,:,:,2]-5607.662795353248)/200.62593105865764 - # normalize:(x-min(x))/(max(x)-min(x)) - #x_processed = np.zeros(shape=X.shape) - #x_processed[:,:,:,0] = (x_preprocessed[:,:,:,0]-np.amin(x_preprocessed[:,:,:,0]))/(np.amax(x_preprocessed[:,:,:,0])-np.amin(x_preprocessed[:,:,:,0])) - #x_processed[:,:,:,1] = (x_preprocessed[:,:,:,1]-np.amin(x_preprocessed[:,:,:,1]))/(np.amax(x_preprocessed[:,:,:,1])-np.amin(x_preprocessed[:,:,:,1])) - #x_processed[:,:,:,2] = (x_preprocessed[:,:,:,2]-np.amin(x_preprocessed[:,:,:,2]))/(np.amax(x_preprocessed[:,:,:,2])-np.amin(x_preprocessed[:,:,:,2])) - - return x_processed.astype(np.float32) - #return X.astype(np.float32) / 255 - - def create_all(self): - X_all = np.zeros((self.N_sequences, self.nt) + self.im_shape, np.float32) - for i, idx in enumerate(self.possible_starts): - X_all[i] = self.preprocess(self.X[idx:idx+self.nt]) - return X_all diff --git a/workflow_parallel_frame_prediction/Training/devel_horovodJob.sh b/workflow_parallel_frame_prediction/Training/devel_horovodJob.sh deleted file mode 100644 index 6b442c18..00000000 --- a/workflow_parallel_frame_prediction/Training/devel_horovodJob.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -#SBATCH --account=deepacf -# budget account where contingent is taken from# TASKS = NODES * GPUS_PER_NODE -#SBATCH --nodes=1 -#SBATCH --ntasks-per-node=2 -#SBATCH --ntasks=2 -# can be omitted if --nodes and --ntasks-per-node -# are given -# SBATCH --cpus-per-task=1 -# for OpenMP/hybrid jobs only -#SBATCH --output=horovod-%j.out -# if keyword omitted: Default is slurm-%j.out in -# the submission directory (%j is replaced by -# the job ID). -#SBATCH --error=horovod-%j.err -# if keyword omitted: Default is slurm-%j.out in -# the submission directory. -#SBATCH --time=00:20:00 -#SBATCH --gres=gpu:2 -#SBATCH --partition=develgpus -#SBATCH --mail-user=b.gong@fz-juelich.de -#SBATCH --mail-type=ALL - -#create a folder to save the output -jutil env activate -p deepacf -module --force purge -module load Stages/Devel-2019a -module load GCC/8.3.0 -module load MVAPICH2/2.3.2-GDR -module load Stages/2019a -module load Horovod/0.16.2-GPU-Python-3.6.8 -module load Keras/2.2.4-GPU-Python-3.6.8 -#module load ParaStationMPI/5.2.2-1 -#module load h5py/2.9.0-Python-3.6.8 -# *** start of job script ***: -# Note: The current working directory at this point is -# the directory where sbatch was executed. -# export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} -# *** start of job script *** -# Note: The current working directory at this point is -# the directory where sbatch was executed. -# export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} -srun --cpu_bind=none python3.6 kitti_train_horovod.py diff --git a/workflow_parallel_frame_prediction/Training/evaluate_multistep.py b/workflow_parallel_frame_prediction/Training/evaluate_multistep.py deleted file mode 100644 index a555a929..00000000 --- a/workflow_parallel_frame_prediction/Training/evaluate_multistep.py +++ /dev/null @@ -1,121 +0,0 @@ -''' -Evaluate trained PredNet -Calculates mean-squared error and plots predictions. -''' - -import os -#import sys, argparse -import numpy as np -#from six.moves import cPickle -import matplotlib -matplotlib.use('Agg') -import matplotlib.pyplot as plt -import matplotlib.gridspec as gridspec - -from keras import backend as K -from keras.models import Model, model_from_json -from keras.layers import Input, Dense, Flatten - -from prednet import PredNet -from data_utils import SequenceGenerator -from kitti_settings import * -#from scipy.misc import imsave - -##Just for checking how the shape is after generator.create_all() from Sequence Generator -#import hickle as hkl -## -n_plot = 10 #number of plots -batch_size = 10 -nt = 15 #number of timesteps used for sequences in training -numtests = 18 -extrap = 10 #frame number from where extrapolation will start to be produced - -#parser = argparse.ArgumentParser() -#parser.add_argument('-ft', help="fine-tune multistep: add extrap time") -#args=parser.parse_args() - -weights_file = os.path.join(WEIGHTS_DIR, 'tensorflow_weights/prednet_kitti_weights-extrapfinetuned.hdf5') -json_file = os.path.join(WEIGHTS_DIR, 'prednet_kitti_model-extrapfinetuned.json') -test_file = os.path.join(DATA_DIR, 'X_test.hkl') -test_sources = os.path.join(DATA_DIR, 'sources_test.hkl') - -#if args.ft is not None: -# extrap = int(args.ft) -# nt = extrap + 5 -# weights_file = os.path.join(MODELS_DIR, 'prednet_ee_weights-extrapfinetuned.hdf5') -# json_file = os.path.join(MODELS_DIR, 'prednet_ee_model-extrapfinetuned.json') - -# Load trained model -f = open(json_file, 'r') -json_string = f.read() -f.close() -train_model = model_from_json(json_string, custom_objects = {'PredNet': PredNet}) -train_model.load_weights(weights_file) - -# Create testing model (to output predictions) -layer_config = train_model.layers[1].get_config() -layer_config['output_mode'] = 'prediction' #'prediction' -layer_config['extrap_start_time'] = extrap; -data_format = layer_config['data_format'] if 'data_format' in layer_config else layer_config['dim_ordering'] -test_prednet = PredNet(weights=train_model.layers[1].get_weights(), **layer_config) -input_shape = list(train_model.layers[0].batch_input_shape[1:]) -input_shape[0] = nt -inputs = Input(shape=tuple(input_shape)) -predictions = test_prednet(inputs) -test_model = Model(inputs=inputs, outputs=predictions) - -test_generator = SequenceGenerator(test_file, test_sources, nt, sequence_start_mode='unique', data_format=data_format) # orig: unique -X_test = test_generator.create_all() -X_hat = test_model.predict(X_test, batch_size) -if data_format == 'channels_first': - X_test = np.transpose(X_test, (0, 1, 3, 4, 2)) - X_hat = np.transpose(X_hat, (0, 1, 3, 4, 2)) - -# Compare MSE of PredNet predictions vs. using last frame. Write results to prediction_scores.txt -shapeXhat = str(X_hat.shape) #Just have a look at the shapes to be sure we are calculating the right MSE -shapeXtest = str(X_test.shape) -mse_model = np.mean( (X_test[:, 1:,:,:,0] - X_hat[:, 1:,:,:,0])**2 ) # look at all timesteps except the first -mse_model_last = np.mean( (X_test[:, 9,:,:,0] - X_hat[:, 14,:,:,0])**2 ) -#mse_prev = np.mean( (X_test[:, :-1,:,:,0] - X_test[:, 1:,:,:,0])**2 ) -mse_prev = np.mean( (X_test[:, 9,:,:,0] - X_test[:, 14,:,:,0])**2 ) -if not os.path.exists(RESULTS_SAVE_DIR): os.mkdir(RESULTS_SAVE_DIR) -f = open(os.path.join(RESULTS_SAVE_DIR, 'prediction_scores.txt'), 'w') -f.write("Model MSE: %f\n" % mse_model) -f.write("Model MSE from only last prediction in sequence in comparison with extrap start time: %f\n" % mse_model_last) -f.write("Previous Frame MSE last frame vs extrap start time: %f" % mse_prev) -f.write("Shape of X_test: " + shapeXtest) -f.write("") -f.write("Shape of X_hat: " + shapeXhat) -f.close() - -# Plot some predictions -aspect_ratio = float(X_hat.shape[2]) / X_hat.shape[3] -plt.figure(figsize = (nt, 2*aspect_ratio)) -gs = gridspec.GridSpec(2, nt) -gs.update(wspace=0., hspace=0.) -plot_save_dir = os.path.join(RESULTS_SAVE_DIR, 'prediction_plots/') -if not os.path.exists(plot_save_dir): os.mkdir(plot_save_dir) -plot_idx = np.random.permutation(X_test.shape[0])[:n_plot] -for i in plot_idx: - for t in range(nt): - plt.subplot(gs[t]) - plt.imshow(X_test[i,t,:,:,0], interpolation='none') - plt.tick_params(axis='both', which='both', bottom='off', top='off', left='off', right='off', labelbottom='off', labelleft='off') - if t==0: plt.ylabel('Actual', fontsize=10) - - plt.subplot(gs[t + nt]) - plt.imshow(X_hat[i,t,:,:,0], interpolation='none') - plt.tick_params(axis='both', which='both', bottom='off', top='off', left='off', right='off', labelbottom='off', labelleft='off') - if t==0: plt.ylabel('Predicted', fontsize=10) - - plt.savefig(plot_save_dir + 'plot_' + str(i) + '.jpg') - plt.clf() - -#abe -#for test in range(numtests): -# testdir = "tile-" + str(test) -# testdir = os.path.join(plot_save_dir, testdir) -# if not os.path.exists( testdir ) : os.mkdir( testdir ) -# for t in range(nt): -# imsave( testdir + "/pred-%02d.jpg" % (t,), X_hat[test,t] ) -# imsave( testdir + "/orig-%02d.jpg" % (t,), X_test[test,t]) \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/bin/f2py b/workflow_parallel_frame_prediction/Training/hickle/bin/f2py deleted file mode 100755 index fcc774fb..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/bin/f2py +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/local/software/jureca/Stages/2018b/software/Python/3.6.6-GCCcore-7.3.0/bin/python -# EASY-INSTALL-SCRIPT: 'numpy==1.15.2','f2py' -__requires__ = 'numpy==1.15.2' -__import__('pkg_resources').run_script('numpy==1.15.2', 'f2py') diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/__pycache__/site.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/__pycache__/site.cpython-36.pyc deleted file mode 100644 index abc2e28feeb37e7e377c2cf5eadc076e5edb1e93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1482 zcmXr!<>i{1ZxPGP$-wZK0SPcMFfceUFfbI$FfcHrFr+ZHFhnt=GNv$PGZjgsGBh(V zGDI_^Fb6YevLwT_i83%Sh%hiPID_;FFflNsFs3l%Fw{b5##+W2#w?~R<`kx8##*Kt zrWA&3j$)G<hAfs8=4_@Ss~RRAh9awUhFYdPo*Jes)*8kvHjv5^_8Nv1mQ03b=33?& zhAfT}&Kjm>#uSEDCP{``mKw$^jx4Sc?q<eX){0#<EG`VOt7_S5*lJj_nTpG5*mxL< zx(dr`n6sE`K&G+Ru%|F&a~AEXVb9`8VQprt<*4BRi|nf5$l?WwFfs%%6qZ#gfL+g5 z%UQz-Qdz^6&e+Tp!(7W%%U#P8&X6a@!cfAW%~kY?kpTqD%OV-_m?9WzxIq3Y`d3(1 zB~rr)GO>oMhP#HRnT3%doFRpwhAT?|6nYV0Tf!Mi_*2-L8JieO1XI{kI9eD$K6GJd zW^87x<pukkGlj94xt1@5v4$aDs6woU$%P@7ua>Pu7~~&Dh6#*?5#bCq3@i*;LN$Em z3``91LM0+KEGdkV49$!&Ott*A0x1l&g6RykLKQg>(_@or*-At}`eT@Cg=<A>L}~=G znI<q69jOrnxgNwS;j9sAW~>#g5vk$LW}CoRd;>1`q(&%96r`JxAy1@6C`+tHu!gOf ziIJg3FonyUp;mALW8sW&h8iJ|Z7B?(n6hC=VF+f><o0_BN-Vdy0wO~^{QUwPLp-8b z%QN$gjcy4SB$i~vXXX~<7nP(I#V02wXQbX@Db6fOtx|E$FU?8GQ!i0S%gjqrD9K1w zC`wJtQBViTsw?E?r<CTTCNqLeW?*0drCb&U28LizDg>q8bcPy+Sdm)B5{4Q^P`Z(1 zNMT50n#feh63n2<_!6W~lkpZuZen&S$PJoIx0v({Zn0#Rq~@+<DB@&bVEE;$U!Y%{ zT$EUnoS~nbl~tT<Vx*sxnU}7go1<HtT9#UrnWvwTnVg-Is-KgYq+d{3l98WhtY@YV za-nWPVsdt3dTKG4r&mz<i_0b_v$!NVKexb66XZ&eli3)mq~ha~^7BjdY;y9G6LX5~ z^bpE!amUA}rl)7-6{i-J6tOZeFldV3VlJ*MzQvSZe2YCbuPn1DKkpWEdTPlnj)I)T zlC=Dy+*_>01v!}|QS2aZ6{i;5Voy&kNh~QTy2Sz#xy785ns<vmC9^0mF*o%VM|^x* zW=?8+{4H)!FvmlJ^%i$deqsuY!<?C0aEsd$97(Q4MfpXySd(+|i&Jm0q+}+S6!9=H zFhp@Brlf$poswBp#KyqDaEmRmpdd9b<rW*n^_rqZybKHsMSLIv<nt)zg3RP7_TrKh zkgK9tb1OkwIY4G{z|zAlHjpz?i;AScCKi_zr6%SUfeM=_)|AxZ<f16<?7aN)ym*ii z#ZheeIVlDC#kUw!qL}hhqBtQo$0wFVapa|zgB9IkEQn&tD*(qYgx~@j4T%F#q9{%P zr6@)YMh-?EMhQkXCLSgpMj=KXCN4%kMkYosMh*~W;$mcBVq)ZAlwjlot7T$jViIBE zVq|0DU=m^CVPpfTXX0ZLU}RxrVd7!rVG;q!F!C_-F!C`Ksepn3lwSQbAskRdfFdM5 e9^x!e0)()@4&<<bM2sESiJ$=HaOYrTV*~(<@OyOt diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/easy-install.pth b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/easy-install.pth deleted file mode 100755 index 09ac2825..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/easy-install.pth +++ /dev/null @@ -1,4 +0,0 @@ -./hickle-3.4.3-py3.6.egg -/usr/local/software/jureca/Stages/2018b/software/h5py/2.8.0-ipsmpi-2018b-Python-3.6.6/lib/python3.6/site-packages/h5py-2.8.0-py3.6-linux-x86_64.egg -/usr/local/software/jureca/Stages/2018b/software/SciPy-Stack/2018b-gcccoremkl-7.3.0-2019.0.117-Python-3.6.6/lib/python3.6/site-packages/numpy-1.15.2-py3.6-linux-x86_64.egg -/usr/local/software/jureca/Stages/2018b/software/Python/3.6.6-GCCcore-7.3.0/lib/python3.6/site-packages/six-1.11.0-py3.6.egg diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/PKG-INFO b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/PKG-INFO deleted file mode 100755 index 5f821450..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/PKG-INFO +++ /dev/null @@ -1,207 +0,0 @@ -Metadata-Version: 2.1 -Name: hickle -Version: 3.4.3 -Summary: Hickle - a HDF5 based version of pickle -Home-page: http://github.com/telegraphic/hickle -Author: Danny Price -Author-email: dan@thetelegraphic.com -License: UNKNOWN -Download-URL: https://github.com/telegraphic/hickle/archive/3.4.3.tar.gz -Description: [](https://travis-ci.org/telegraphic/hickle) - [](http://joss.theoj.org/papers/0c6638f84a1a574913ed7c6dd1051847) - - - Hickle - ====== - - Hickle is a [HDF5](https://www.hdfgroup.org/solutions/hdf5/) based clone of `pickle`, with a twist: instead of serializing to a pickle file, - Hickle dumps to a HDF5 file (Hierarchical Data Format). It is designed to be a "drop-in" replacement for pickle (for common data objects), but is - really an amalgam of `h5py` and `dill`/`pickle` with extended functionality. - - That is: `hickle` is a neat little way of dumping python variables to HDF5 files that can be read in most programming - languages, not just Python. Hickle is fast, and allows for transparent compression of your data (LZF / GZIP). - - Why use Hickle? - --------------- - - While `hickle` is designed to be a drop-in replacement for `pickle` (or something like `json`), it works very differently. - Instead of serializing / json-izing, it instead stores the data using the excellent [h5py](https://www.h5py.org/) module. - - The main reasons to use hickle are: - - 1. It's faster than pickle and cPickle. - 2. It stores data in HDF5. - 3. You can easily compress your data. - - The main reasons not to use hickle are: - - 1. You don't want to store your data in HDF5. While hickle can serialize arbitrary python objects, this functionality is provided only for convenience, and you're probably better off just using the pickle module. - 2. You want to convert your data in human-readable JSON/YAML, in which case, you should do that instead. - - So, if you want your data in HDF5, or if your pickling is taking too long, give hickle a try. - Hickle is particularly good at storing large numpy arrays, thanks to `h5py` running under the hood. - - Documentation - ------------- - - Documentation for hickle can be found at [telegraphic.github.io/hickle/](http://telegraphic.github.io/hickle/). - - - Usage example - ------------- - - Hickle is nice and easy to use, and should look very familiar to those of you who have pickled before. - - In short, `hickle` provides two methods: a [hickle.load](http://telegraphic.github.io/hickle/toc.html#hickle.load) - method, for loading hickle files, and a [hickle.dump](http://telegraphic.github.io/hickle/toc.html#hickle.dump) - method, for dumping data into HDF5. Here's a complete example: - - ```python - import os - import hickle as hkl - import numpy as np - - # Create a numpy array of data - array_obj = np.ones(32768, dtype='float32') - - # Dump to file - hkl.dump(array_obj, 'test.hkl', mode='w') - - # Dump data, with compression - hkl.dump(array_obj, 'test_gzip.hkl', mode='w', compression='gzip') - - # Compare filesizes - print('uncompressed: %i bytes' % os.path.getsize('test.hkl')) - print('compressed: %i bytes' % os.path.getsize('test_gzip.hkl')) - - # Load data - array_hkl = hkl.load('test_gzip.hkl') - - # Check the two are the same file - assert array_hkl.dtype == array_obj.dtype - assert np.all((array_hkl, array_obj)) - ``` - - ### HDF5 compression options - - A major benefit of `hickle` over `pickle` is that it allows fancy HDF5 features to - be applied, by passing on keyword arguments on to `h5py`. So, you can do things like: - ```python - hkl.dump(array_obj, 'test_lzf.hkl', mode='w', compression='lzf', scaleoffset=0, - chunks=(100, 100), shuffle=True, fletcher32=True) - ``` - A detailed explanation of these keywords is given at http://docs.h5py.org/en/latest/high/dataset.html, - but we give a quick rundown below. - - In HDF5, datasets are stored as B-trees, a tree data structure that has speed benefits over contiguous - blocks of data. In the B-tree, data are split into [chunks](http://docs.h5py.org/en/latest/high/dataset.html#chunked-storage), - which is leveraged to allow [dataset resizing](http://docs.h5py.org/en/latest/high/dataset.html#resizable-datasets) and - compression via [filter pipelines](http://docs.h5py.org/en/latest/high/dataset.html#filter-pipeline). Filters such as - `shuffle` and `scaleoffset` move your data around to improve compression ratios, and `fletcher32` computes a checksum. - These file-level options are abstracted away from the data model. - - Recent changes - -------------- - - * December 2018: Accepted to Journal of Open-Source Software (JOSS). - * June 2018: Major refactor and support for Python 3. - * Aug 2016: Added support for scipy sparse matrices `bsr_matrix`, `csr_matrix` and `csc_matrix`. - - Performance comparison - ---------------------- - - Hickle runs a lot faster than pickle with its default settings, and a little faster than pickle with `protocol=2` set: - - ```Python - In [1]: import numpy as np - - In [2]: x = np.random.random((2000, 2000)) - - In [3]: import pickle - - In [4]: f = open('foo.pkl', 'w') - - In [5]: %time pickle.dump(x, f) # slow by default - CPU times: user 2 s, sys: 274 ms, total: 2.27 s - Wall time: 2.74 s - - In [6]: f = open('foo.pkl', 'w') - - In [7]: %time pickle.dump(x, f, protocol=2) # actually very fast - CPU times: user 18.8 ms, sys: 36 ms, total: 54.8 ms - Wall time: 55.6 ms - - In [8]: import hickle - - In [9]: f = open('foo.hkl', 'w') - - In [10]: %time hickle.dump(x, f) # a bit faster - dumping <type 'numpy.ndarray'> to file <HDF5 file "foo.hkl" (mode r+)> - CPU times: user 764 us, sys: 35.6 ms, total: 36.4 ms - Wall time: 36.2 ms - ``` - - So if you do continue to use pickle, add the `protocol=2` keyword (thanks @mrocklin for pointing this out). - - For storing python dictionaries of lists, hickle beats the python json encoder, but is slower than uJson. For a dictionary with 64 entries, each containing a 4096 length list of random numbers, the times are: - - - json took 2633.263 ms - uJson took 138.482 ms - hickle took 232.181 ms - - - It should be noted that these comparisons are of course not fair: storing in HDF5 will not help you convert something into JSON, nor will it help you serialize a string. But for quick storage of the contents of a python variable, it's a pretty good option. - - Installation guidelines (for Linux and Mac OS). - ----------------------------------------------- - - ### Easy method - Install with `pip` by running `pip install hickle` from the command line. - - ### Manual install - - 1. You should have Python 2.7 and above installed - - 2. Install h5py - (Official page: http://docs.h5py.org/en/latest/build.html) - - 3. Install hdf5 - (Official page: http://www.hdfgroup.org/ftp/HDF5/current/src/unpacked/release_docs/INSTALL) - - 4. Download `hickle`: - via terminal: git clone https://github.com/telegraphic/hickle.git - via manual download: Go to https://github.com/telegraphic/hickle and on right hand side you will find `Download ZIP` file - - 5. cd to your downloaded `hickle` directory - - 6. Then run the following command in the `hickle` directory: - `python setup.py install` - - ### Testing - - Once installed from source, run `python setup.py test` to check it's all working. - - - Bugs & contributing - -------------------- - - Contributions and bugfixes are very welcome. Please check out our [contribution guidelines](https://github.com/telegraphic/hickle/blob/master/CONTRIBUTING.md) - for more details on how to contribute to development. - - - Referencing hickle - ------------------ - - If you use `hickle` in academic research, we would be grateful if you could reference [our paper](http://joss.theoj.org/papers/0c6638f84a1a574913ed7c6dd1051847) in the [Journal of Open-Source Software (JOSS)](http://joss.theoj.org/about). - - ``` - Price et al., (2018). Hickle: A HDF5-based python pickle replacement. Journal of Open Source Software, 3(32), 1115, https://doi.org/10.21105/joss.01115 - ``` - -Keywords: pickle,hdf5,data storage,data export -Platform: Cross platform (Linux -Platform: Mac OSX -Platform: Windows) -Requires-Python: >=2.7 -Description-Content-Type: text/markdown diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/SOURCES.txt b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/SOURCES.txt deleted file mode 100755 index bf56f059..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/SOURCES.txt +++ /dev/null @@ -1,52 +0,0 @@ -.gitignore -.nojekyll -.pylintrc -.travis.yml -CODE_OF_CONDUCT.md -CONTRIBUTING.md -LICENSE -README.md -_config.yml -paper.bib -paper.md -requirements.txt -setup.cfg -setup.py -docs/Makefile -docs/make_docs.sh -docs/source/conf.py -docs/source/index.md -docs/source/toc.rst -docs/source/_static/empty.txt -docs/source/_templates/empty.txt -hickle/__init__.py -hickle/helpers.py -hickle/hickle.py -hickle/hickle_legacy.py -hickle/hickle_legacy2.py -hickle/lookup.py -hickle.egg-info/PKG-INFO -hickle.egg-info/SOURCES.txt -hickle.egg-info/dependency_links.txt -hickle.egg-info/not-zip-safe -hickle.egg-info/requires.txt -hickle.egg-info/top_level.txt -hickle/loaders/__init__.py -hickle/loaders/load_astropy.py -hickle/loaders/load_numpy.py -hickle/loaders/load_pandas.py -hickle/loaders/load_python.py -hickle/loaders/load_python3.py -hickle/loaders/load_scipy.py -tests/__init__.py -tests/test_astropy.py -tests/test_hickle.py -tests/test_hickle_helpers.py -tests/test_legacy_load.py -tests/test_scipy.py -tests/legacy_hkls/generate_test_hickle.py -tests/legacy_hkls/hickle_1_1_0.hkl -tests/legacy_hkls/hickle_1_3_2.hkl -tests/legacy_hkls/hickle_1_4_0.hkl -tests/legacy_hkls/hickle_2_0_5.hkl -tests/legacy_hkls/hickle_2_1_0.hkl \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/dependency_links.txt b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/dependency_links.txt deleted file mode 100755 index 8b137891..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/not-zip-safe b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/not-zip-safe deleted file mode 100755 index 8b137891..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/not-zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/requires.txt b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/requires.txt deleted file mode 100755 index 8ccd5558..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/requires.txt +++ /dev/null @@ -1,2 +0,0 @@ -numpy -h5py diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/top_level.txt b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/top_level.txt deleted file mode 100755 index ce3b9fb8..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/EGG-INFO/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -hickle -tests diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__init__.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__init__.py deleted file mode 100755 index 46e2ea2c..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .hickle import dump, load -from .hickle import __version__ - - diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/__init__.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 638a67eaaa3ab784f6e31d96cc63e6c3a1acc1e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278 zcmXr!<>i`^S{>`iz`*dB0SPcMFfceUFfbG=FfcHrFr+Z%Fyt~uG3GKwF)@PpOgRj> z%u&pY3@OaP44N!285tNDG?{L(q?G0s++xYePfXEdyu}?KUzS=_oSB~&AMdBha*Hh^ zGdVjawFqQ*5i<h=LlFxD1H(#&A~p~kMEuIvFVHV2%FjwoF40fU$|_DaG15=U%uCnL z&CxARElVxR%+rUMqMwtQq+d{3l98WhtY@ZQoLQ2pTacKXotU0l3{|3QtY@NUtXoiN qtY@Z|nw}07){l?R%*!l^kJl@xyv1RYo1apelWGU@K{3c>0*nCn_DL-O diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/helpers.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/helpers.cpython-36.pyc deleted file mode 100644 index 944de5cd7f681a49a8d9fbf2024be8e218cadb71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3266 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 J=aAqK1OOHdKnef= diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle.cpython-36.pyc deleted file mode 100644 index ff8228b3857699bdd27288d585d63a1bcfa08c69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17742 zcmXr!<>i`^S{<7f#K7>F0SPEEFfceUFfbGsF)=WtFhnt=Fs3l&Fy=BvG37ExG3T;G zu`q(fm~&X8SW_5Nm~+^o*isl%SaR5NIifgnIioni@~k;rx!h6QU^a6OPZTd$EngIW z3R?<$jzF$plwht<lu)j4lyI&{ln5h33R?<Cj%cn}lvu8Klz6U0ltiv%lw__{loVKw zGe<O6I!c<6p;9J=F@-BfCRa8}7Hm3qj$E#MlsqFtI76NY3qz_xHdoORMg|a!WXNNR z0J)YYM=@6^N-0-4N;y|0N+nk{N)@b^IY%u@EmgVbL#kSqdXz>b57?EOQCi^)c}@_s zCNLJ+fy`oLfXZrvW#!<q77$smPOT^{h@B7;ET$8sQ^}Xgk;2=|n57$~7tW9;#ln!v znawqUv8Vv5moG{WqQjjbg+E20g&{>CRkoQqO5dF!MKDFEg&{=<%r|gnND)pEX<<ka z0rL&r8B#=3#9A0q#K3$bcZL-46p0pw6p2*hX67gpcZL+n6sZ=56sc7HEYoJ@C^L74 z6zLS17KRj=RQ@dUX67i16x$T}6onSXD9aSP6vY&!7RD&66#Ep_6txz{DC-pU6pa>! zD4P_A6wMT^7RD&s6vq_p6rC2vD7zG=6x|fP7RD(16z3HE6oVGVC<k|j6vGsw7KRj~ zRL5rKD5n(T6q6Q)DCZQ@6tfnFD3=tM6!R2|7RD&o6w4H=7KSLd6zde57KSMI6y{(C zP1i&bW(Ec>Wrd8)<m{YOy@E<EF6W}u#FEq$g``Ram&ClhN`-);%;Z!BBLhP-T>~Rs z17kfdE)TGBh0J1wL<J8QH&cbA#NyNxh2)(4yi|q!G=%`Lyq<z*UU5lkVhTv8IJGD< zF(<PsGcR4CBwry>p#ZFgD=jl8RYw78U`lCjK`}%cY%EApPr<VUWK&9Nab|j6Y6?g? zDODk{SfMyGH!~-(2qXY8Od&ImtF$;V9V}arUtFA-1Tws!D8DQ-1!QreLQZ~SiiV~_ zVqS^@$TAI0g|yPV<dV$%JUuQhWn~4w{F2mSxCb*5ixo=B^A&OvGxHP@Q_2$aN)ppk zixu+AQj4ITwBj<<RPb>Oa(7h-@O1X}aaHhe^mFm?^mEr!2+ae#3u<#>QF<!W*C78C z=j4~`fV@$XkqT3pTEtb9nwV0o01`{hE6FT^>nO<p8<Up;_Cm2jW{E;(UP-<}Zfb6R zQ6(s-6_WFF3lfVmi}Ukzz_9`j+hT>pqErQV;HBjkDdd1%l9E`GSe#l?tfvqHG8&>T zKQE^eY(Z*@LU~4No<d@Ba%ypLYKk5gmyxD|bC7><utI>3V~Cr7kgq~;Xh48}P>7y_ zV@XMBZb1pig(dk4r4VnY!Xp{#>lB6jJcaPgyp;U%Vy^r=1)t2k(h6`?lz~!MS!z*n zA}C~XGP6^2DnZejmYA8NP@Y+mp^#cslwVY=0FqKr^2{qvO)f1;RVXeg%FIjW0*7*{ zk{;OC3ZO(&tWchrlLPjNLRw~CDmb8X^7GO`0iKj!lA(~Bn4FQBms+flkyw_>m0?;? zsgRjhT#}fR1NQ7oP${j+e2YIZsW?BUv?Mh?Gq)hWsN@z$N@iJRab|wrExv-H%)F9# zSo-nPWV$7go>~&0k_mEFQYk1=-4by@;`!y5xaF7TrD!tV;>pP@Ni9muiBBy{%z4Sk zz`&r%a*G3`y`-`r^%iGweo;w$c4}quEy3iB)a2~=%;I>kj-;H_TM|$qkO@gSsUV5m zc#u9#)>~X4x;Q>1Gr8mzUq*HgSRBe1gvjOPm&BLk$Ahf6C6b(<SCW{Sms*6ZPy!*E zomz<`qse$n6l!^Kd|paoQBh)LJSb8$8E<jARwSnufPAgVc#Fd?KQA?;vLIEH<rZ^5 zq!EZPzQqFynY?s}fwy=w^GZ_FVK(1lgA_tl>IQlSdIk!*3I#c-iN&d~Xi+H31Qi+u z`o*awr3HEgmC2wef?+0DO{&1az>vxi#hAhn#gxJr#hk*F!ra0T#gf93!rH<R#hStv z%%I7Bi_<MLC)E{{sH(IS9P<=XVQyC_O3Vb6WtnN<ObAL$pfs75S)5U+kPM0_kd+`B zgq=Z^Hwy!(@(yOuWb|9fpvicPr8qSwtw@@IfdNeX%GEE>FDS~-N=+`&PtM9JPBt;p zPs+?o*U!z-Elw><Ey~Q(hxlDTCo@UEpt2+*KhIdtOusm@BvrQ{F*zGl=s=a|8ta+p z8S55Q8ta+qrKYDtg`t#QLFFxu`1s7c%#!$cUy$QK0mHypB?R}c9!wgKXBdMSG@1OW zLY))y^72a*@(WV)z}ZSqApjC51&PJQ3aObT8L34IiD0R`#9UZ@)PV{q<R^jrtfP<* zQUuCkdLUPT14WauNCp-_V1Xi81_p*(?D6r%B}MV^0Z2|41Ze_Cl^#^qPm>MgOOTcE z@wd3*<8$*<N^?@<<8SfA#}}3+=0IiG<Kt8EljGxy<Um%*g9v!6AS^ACVqjqK23g3) zz`(%4$im3M3>Kp(f$=-%<QJ!=z}-&OWCnIT_8<iNH5}v{Xv|BXIfR7xPk~p$3ZR-W zDK#|@RL6s=1M(9>9wa#tlN^dbQ5J>d7jaC#fRl@#CR-6G;}<D{;uzGbE>Z@u@W;Cf z0|P@S$aJK52Z>P>?>v6_zKJEt8Q=t4<%6$mfn*N_P@xPeVn8{qG%qE!sJJ9QKSe<! zzlcjgK|!Iov;b7`q^4-%$*>II(uYv8NCJ5lnk+<--AO{4Z~=SFN}(hpvl!y^{4@nf zkp<1~3dxXCBPmrOIX|x~wFuOj1h-WZVeL$O4h6+|Dw0D*&>TuZgsU<zFvNq521hs( zIHQBaD2i~-kbIYXaG+F~VU2B2lPfPjPd78SASX39H4hXVutq~-PG(6Z#qpX0@)I;( zh2YL1AyUo2?uSMyirYXLKTo|x0i5@deNdTNqDLqi^O4*oi0m#3;!ur&fguZIE;tS$ zg*8YFB@RJVGq_(ZfYBNVX3%85B^V6tjijc8Cl=*p=A~DKf#ME1N0uiRE1+gcE^vMf z$w*ZIwVfd?%%oHWSkERkMWM79)C7h!NA<v}{WMvymQ2{{A$5?qKp51Z;9y~4ECPw3 zc#Ij;_y8%<LGxHULmDHvslyS)0%n7nI~-B0?F=joQJ^Ld+bup1Q}?3$(t_}!#Dap< zqN*bbV6H+rgs)JNkyxSt=_{pzI(8*RiOJdVC7HRY#R}QwiACvpkN`jy2loJz^7C_2 z6Y~_(auU-arX(lkDS$(!1k{RmOUx-w)ln$Uhe(!`=YxX=)U+yANQQPd6H63QGSkvh zi&FDS6d;y@oA99Kxk6?Ns56wDn4{q9VhT!<8L7pP@P+3cP{@G7jUN;`pc<frp$0S< z!PLxL!<52k!%)Il!c@c1%#_7k!&t-A2WsLl``zM3@=b^)%Pscw)RM%KlA>Fz#ia$Q zMMWB*RtX=(k@28tFHSAdWCpigZm}d5r5E2~1BXp9r~w=wpPZ9eTpS+{&KTepO%W)f zT0w3CIgWu*fU!yzH6HX(4TpOOq#lI99@1i9U?^cIVFY`C3F3iT<`Tvl=6L237Pv>5 z<5_D!{d#7<B25Mch7e7*B5hDT2=)aJ)S`4yA}G=aiGz#<tJGuxd#OklB&rAUGb>n` zCL=^4IJtsaXhjAL3=Ewh|8RhkBBKx^8zUcMl{9ugLCj#sngc)q12*jzFEreeQ*&}) zVF$7hW;xhikQeGf_JZ?0D+?nJ3pjG9mOXeqOhJt`SnfEZ0A(qF%5P9>MFAuYNx~y6 zmw=N<h$c%BIK6;VlrbowfT9qZ84xK47HgmwL}Y<!pr`{SXK)sfK?!S0asYD;b3984 zD^d<%L(Ku~kQ@MZFDUJT6AdI$gM9<aCm5-}$Pm;a$C~zMfjoke_NB0ThNz@pWCRLE za7cj&SkQqJJjlfpK$amTc#zmF#-fm9P-zFse;_$-1_lOjKXeDEAIezE3@Z6RrCk<t z8dEb<kwpzd7E2977Aq4&ElVw94MP@NGXo<-340bt4NDDUGgB>VUJh6fXERe#NDV_R z3yNF-SdOcNJ&QYwCyN7Y=Cn$#8ip+1T9$BzJP8(t625G%qAtkrY6*W6BV>5BhM|@< zg{hV~kFP|ah9OI^nURs9M5u|egsX-%Ua*F#hBaQehP8${jR{mKC%$21U{G)bcP7DI zgw!I1jMSWh)FSv09b_n|I6pTPG9ILmk(if~lbM&UrvMtnDh9PY!CH~(my(R4{L=Ic z^e$<l0ys;9>L76cG^@0@1m58XbswRXonujYu@%@jP+L4rK?9-#q#4|q1#5<kYG_)4 zO9)*^WtEnhTBM_ps+X<@_7TWPP(K)?9okNYRA3-ubMsSD6*P)Vil9b-{h$C6)l={X zjmQ<H7M5lfrKTukrh(-^t&F5fguxI8APhvR)D$#8)w8CRLI|ij2iL3$nR(!mGHZpB z(xN<t{IoQXxs~~)3gwA;C6G2c$cDrcxW_@R1Y`6%x+EXeWJoDZPDQGuL7psD(13V8 zzX)DwD}aZNG@(Ho;-)Ebiz~AjJnWX2oO+7|r0*6}X8tYSkkpD2Pk(3$e2WDXdbe0W z0dk8q8Pu=7#gt)siv?657m0(i5IAEn$7kf+Vg(see2W7_fwggkCFYbuhI)!Xy}Mhi z;Bh-h5diA?gG)C}wp)y8MOGlQKqbO0F0eK6pe9Wbs3m!eIl~lbOb1-B-QosW5)T?3 zNiA9k%BrABih-AfS%8s`k%N(sk&BUqk&jV?k%^HD!ee4%;$mcBVq;`uEOKLDV1Q?2 zE(Qh$R@gX%3?l<WIzuf>g$k(7FJUTSPG>1$DPc`#c43I+t7WZW$zrQv1!bo~iExGz z_8Nv}#v+#zjv59~%OH)phPjWCks<F&31<yM30E^yQ38hCjuLK=t_h4q93?y;RxMi% zTMA<~N70rNUWhr(%(d(lbtQZtSr>*_xfrHej#|zV{u<62_B5sxrW%e+#v117Odz`o zCxkQP1=X<Cuw=6pox`xr0>w-lBF%gf&X6a7ZWegnf+f)bR9Lu_<`#eknZW~Q&|C#- za3(5%OJ8tt0UEdmr*?2|fh9dq=M~n^0rkC;!Q;LPMWA8j;><G8@N-fnxI6$4{bNoQ zfHDJW*-%g!pP!Uvh1M4?$p_CfAhKpgJj87p8K&R@L=Vi>w1PSrsvgqA0Ck!XIzeuX z&rDI!$jmFzv{J~-OG&K&`4(E<R6+wly;z|rH7Btovn*91CqFq6G$0Gg@t`RM*a$Mj zP`6v`P&55B1#Yo`%86U-ph<+B)QVfINtGq3#kW|~a`F>PAel@8)GlO8ttd&&ODPfp zafF~vO3*knv~gTy3X)&}jXxKGYNjF{5MKaEA=tyWI8*aVb5n~FOHyyK#)HCFlj{~6 zBn)q{Lj$SE9h4tI&Cw`+kdj2uV0Q{=yrlRRb53zd6lZ2hYA$#*`4(43d~s<K#B8R_ z%v+oVl^}uqq%25d98|x8b8S%|0|Uc3P;Lcv8yR?57$q3_m^m1Qn7P21gPDVohf#=8 zhK++!hzZPM0qeQNSpJJqKN*xuK~*ovU!aN_JaQ<<$iR@oSj#qnv5Kj3RtY#C)-X3S z$1v5h*RrKB)v#wVrZC$ulrW{RG&5!~gZZpB3@J?Mj9@mK4MPb_7Hcg>3VRJl3Wp>^ z4Mz$mnB<aVNMjabsO1FZyDY{OZX1Rg_AIs<mS)CUt{Scso@|byNj2<Q><|&KiCkHX zDIgO;B?4C(Qw=L9kA^ekC9yD+K;}YOAeD6udlpwMcMW?MH>gQaWmd^o!jr{Y!wo81 z!Wr_EpjG=9i0TslEP)i>8g4NLkUXT44`)c>DdB8lj9@_UYuF|*7D>QNjbKRO31-mb zOZ>vbz@QLblv#q98A?$oN-Zc#El$lVfh5%YG*B`IC2LT61r@E}d<zmxO)demp?MgQ z`|^{r6f_`RcTM#Cm#<J<l3xUxL;y`yLZ%!+c^6c2TY-&(8m$B7fNBirtP;3phu8B^ zRVWoA$P7@<D$mGF&Hy<XVinlo;E``V1xIi*1Dw%8wLj8OIjHBHQw-?|gB%3Hpvks^ z5>P6KWKd9r2WuDPgJ)I}a}*Mb(n~?3NIDAYMd}I~p!q@t(6pVVj)Ho*x`IYID1bFV zwy7toD`<fF`gtju5CcJ$fUswJUOu!r0r3Q=zYk_Xf)Sz`R1_4Y7K0|caJoWI!Lgtq zCo{DeJo^Y!4JyST(~Eiv{$Pg}TPc8Mgme_rt1=68P=Yb1DosH{TcH>v0cwbV+XJ9! zI8CrJY;75gz|d3hOj9UMMILS_N-cm)WP_(xK<yductSx@KB%<<HX0NZAPgx%LBk86 zFo2FM6eN~pz`PA+gXSSK^As{t(oDf=1svmvWzf-}l6*Y{m(;Yx(wq|T40cg|eu;uU z*c!KDP%|CujMQ7K&OVO8!9|jwQjtB(H7MBA-|rR+s7$NkP|ef>qax7wRS~F@@e(wu z7sVG48RFsZ7Y|kLSET^1`9QOysVRC2&iSP|Dd4fHqSV~{vQ!1tVogDC^WqjOXe^_+ z2vla>Vh2sIf+jARiz|z7@j!X;nR#jXx0usYOTe9Ra7kAL8WaULdy1?<?qtd@zQqPH z`xd)@FnF-=7DqW`<gEA>3y7u3QxwF&zz_v)c!6p{q{b8rDEx{*<#>?`s6=-K8(L5n z1uF2%Qj2c!WW<BQ3sN=SVod{OL$qT177M5bU|?imC<b-o7=&4v*q8(uxflf)d6?K3 zr5L%GxR^K?xfpqvgct=F*%(0+Ied(Kj1o)&ENqNLpfOUEu@z7k3fyf1bpt_NoMy&a zMo_mYld+bmhAE4=gauT})i7nT)-aZ^H8a&RgL{^YiMgP*M>uG-3>0mk#SM^L1D<Iw zPgN)>sstrBP}3M(;MhZZC!j13Z61Kr1*ne9%+E_Ks)Vke0JZYV5_3Q!VEJhZi3-V} z>CfVl#1inZv7Q2GB}7pwsL>8tA&{J3RFs+wX{Dogl|Z8wi3;hNWvO|P#stW%7)2*2 z^+PIM^n$Y_Um+(yKU=r7K%pGuRd{O&G{Ik-3QGK-2m#ZX#o3Ud!61m^5FMsm&{T+( z0zxy$sNxK8f=x<QC<V>5f(i>zLk`q{02!C4ke6Bxc5`tm#BZAHMKPds;|EGN!qBD! zDD+?>a<|w@3sMqGQj2&&%0SZ`w>a|h<H5FTvVarjEyj{49#9w*$AkP;T5yXMERCMb zL}A85$}gy5b5Obiwb2>4IT$$@xtMsEii(ii@1Pt88r}f620$~L&=kc|!vbkd!&>Dj zpn*rGsxJzVbv6o#FrUI&tDx!wQdS_Et&q?~)OdKK4HPYq0vx0a+LTfl;Pxgs!TV`4 zf<sM{6&xi+!JycJxADM3rD)Mn1e(M40R=uNa2dEbn870OZWBlpo{>QXObufeLkeRJ z6R3#-8XyIa`7(l<T%ghMW>9mBIg2HQ#fAZ#nOUn&AtC~l?7$63EKvcf7_h~{U<%$U zc2E|ISIxY|npm8inR$yX6I{=OGmj=KxO~6GTwGEF7P!ThnwOlPl3El88tZ~&5~LUb zO^l*PhCc%XLkuV~K=l~|2OpyhV-ZLU9vz@63zQSUxnLCo0|QEQuz*TeP;U|?I#?jl zQBegNqH1PvVTjF(VX9@VWh-H;VJ%^AW-1D+VaZ}hVXa{WM=E<BABbPV2<ibhGuE=F zuz}mq;7A4Az}k!&;p|x~DeN{3B^)(u;GQc-3MW#})g+uDg)5jrlRHrt)INn|OHg|V z6qwLn8K^K#O-#;E$W8?<6H)+`J&=+ck|w~b#t@}m2&j7rF73-wiz*c$D~CWsEAVm< z(qt?xPK6ZY@P4NPxGMzCETGJrn_7~Q4_Wb6nwgWLP+Fjnk(pYQSd^TR32Lr@otT@S zlA2QtY3HVZ+M}Qn1U_?*C<z=vc4ZcWySqi1C13+e^5JE3W?s4ucvV@kLUw8aXmuH) z{|hOPK+6L`t^#3DegLn`fiCaM%mb?iEw4*0D%Mv>$pqC*pp|Km5F(-MvQ|J;5J&+H zvK52}Nsa?K1)kxGia{k=35WnyR8>r>Ma7(;(b&x767cG*TO6=;RFFO`sDbCF$qCMq zMWrx(MP(osC_mm}1@&x;!JTPH=Nr^()#SidZborufR}rLi>_PD*{PL9p!FX`*m7_# z0|P@QC<lYO?+ko=j516@pf(f}A0rQw3{w$E9-f;)xg1o$f^)MIcm^s9Gy}z0%TmLb z#RMs4Ygp15Q<!?0YFSg5(-~`6vzS4JE2uA<!dk)x%I#tdpj-@ER}5NtmB<HbJ$a@n z<bjq|mLz9@(qnF7N~#WI<&{Dr(qb$!(oPDb4G!)|l%(c@Ob5;4g6n$F%05uMf$(5V zMxeE0pezmUFF<CI!9{hIp(=E(1;{IiH6l9TwgY$tBV>XeF%|8n$#IJfV#F<0P>Y}# zQoVu_S5X=$nWcjWP-+FwGHbG7Pg)QoQa}y*TZ}2_6#{62zYUa}z)d3#E=CbX9wt7< zB9J)ti8;^+Df03>@LV-$i5>@Hi5}9NHFrRzGi-rkqAMunI6{hKUC^RKXr~;q5EfFT zf}5?0Dd2zsuWp4TA<sO8{Gyap@LJ&{SW%j&P*Rkd3Nfj;q^LBxq_ikiN1;4bAukoN z&NwM26<i*pn+&lv5wykyvVaoYY5*l)NS9kfQvp(ZLrUNP$RK4&X+aKXc0Dfz)LkuB zNXZ9x+!Awg^2@<%YQW2Jixt2V$)KV2vdom!Vz2`e6>>6*OCZjLb~wOO_Sn|hfK=)z zfGyJjSp*sm0F|W>x4`>BpkfHrd;;NO(BL>|ycsgb3>ptgVW?q<X9kljV3IWjvd{=N zuUrR8L!d=gxA+h%MnR42B1@1=IjCg;S?C9w+CmJ&fwV0Kr5#YCfq{{a5i}@XC4v;; zm<w1yN<k$OxZk!0)V^TIVklwEVrpi{W-C$v&5vg>NHWwi)_}{YV1^oyJh&&91=>Hs z)XbF4RJ0_Wp_Zw_rv}v4Z~^t|ve>fNQ<$3>K_hOpEH%to94V}l47IE^tR<XKv#Uxt zYd~UbpfT=dPzlJC#RVF1V`M0F2nX$_U~gdnnFwl;l(3X=*D%$vH#0Reg4__ykirqn zpvhIWQNbCqB1$2xC_h&L$*-V}4|Ek(GHARCR1AQZS3$dMpdt&_yHWtHFV%rBzXY{a zaK$$`;ehnQu||H8LOyuiCMcd1iVIScGt)9bQ%iZ^4j*`FEo9^cqz9>Hiv&d}C<eg8 z6Yw+y8leEi38*n&EW!Yqxu{`?<pIS(3WFrWM5aO((Bd?(CUE(o$#jcJ&)^mdsD=Xz zKnT!S>Mt%EkWWAZPj-7jX#-?98$*>kQb_4R7nSMRfJV1-itY3edi-Ag|NsBLCQlJ) zr9csA@y{(5&?0I`6$|P<LaJC$>b%8TT#%DlQUpq*MS`H7B^xB;-eRuGEYRctFNlcZ zg4!0JmRHmQ3V=osQ3)bI8l$*M^1<WJAo&WAC^&(G36O_C<LTffa4SK+0VR0`cF?pC z2csAx3#j4+4OlROx|DoOe2jcdRl-<&s)>C81<16b4v?KjAOdVBh=64^ko`rV96B3h zH>fh_U}s_EVFQc7qYqXDfU^`R#7aQ@Ck9YcyNNLcJTqJ61R7mKudgBd13(QvaLW-^ zWP+DZgGxd8ifV8gtdfAPB?f6wP%Q=*(BK5_2U-muRGJ4`^8+4P(qt?GhcC!4h@^3g z7uKPV2N`h)<R?(-U|=rl0(Hbe{s0ZjgTz3^8IpfMjg}IoW+qUQ1SQ490#HRl)Bp}_ zD+A4ja6p+596+$K8g-C}I;f*jo?irS&O;jD;9*B-fk0$~8Z_21IL2_8i}*mv6f`&k zjxkLpNHiCMMA70}7!<{@!5!!j%n4A8g9;i39v-HmZcv<q;u#d@pm`?HfGRl7PeG<) zm?tn+t%D50#4y#e)H2twWHHt-HZ#_;PGGF`N@1#D$zsZ422~uzCM7IQj42=$FcCM9 z2uMW=vm`?;TP05kYYiKyXb)$|Q($2zVaw(!s)0_5u-34put+k1WFb=^HS8&@*-S;- zO4y6mlyGEmrm%qq5>r@H*g@O$YB?AgYB;iZY8Yymnwf$bN_bN^ni-oI^ETD6r*LL7 z6@4mUFM0vi#|72Lox_#OSIf!BP{Rq<$5_LZ!qdx)q_?bwJ%u-$X#!)B4XBd~VU@5? zU@S5Mo5V-7NjhMYSSK(RWt8wYGt_dW@Yis~3zP`faMiFjGl8d^SR@%hJ`M(L0(4_x zC}9C_uiF3(50I@(z_toNZN=+vNSK8)qzKk9Phc!MQp1uZ1ZsRlFr)|uGiVAWg0i}T zPkv&G0&M*-I3IvF4i%*)=jTD%Zs-%ikcJ;>HUafo!IQKg2DJ64gP5WLPx*kPK;zHQ zX&`Xs1l5EfT%4Ge3SUs+l35Izs!>QREy>SKEXhn(NJ#}ZmqCNSpz+(Hq|A~c(C99- zVuv)^iXm+<kZ~aF;;-Q69|CTpL6%hKD}dKaDwO8sq!xp^?5Pm%W)?#l4WL$QX)$OK zadCcWQF1D(aT>*`sR|h-B?VUc`sL;2ddbClSsA5zsVSxUb;bI*;03D1`e0|K>SdJV z=75*Cf%{wqIf;4TNjObN(1BbB8n~y@BuEixA%9UcD7S;kYVh<%l_hlJA1KfjpfeJw zDWFYSVTL*iiHL1wIjQN1$&jsSp!Gg_dYX*4cp;@?JVdT499qM`Ck>%ZX|UO#)x4lC zLrx`p#VKe$M*-R_Hv*@o#5{%koD|3cm{gc^^on8`7#ONNkX;IDC?pnv=XsJ+!Fr%> zSI{Uk(j@3`J`{%=X)+aMfZ87{pyc%uRH#+?5N(^Dp`HN&8^M!JRaVGGW<u6BLtUMk zg5Sx0n!@1eq#|(P4emmM+CsPZ9E*!ni$Dtuz!mo`=FGg3B1cdRi-HJvH}e)lQ4iRI zpkloUw0g9t7o-5xH~}}+Zn1(Zb?|JHCig9NP?UjY?m@v))CW=upEoMX0?jfphq(qt zafZ1D#rryX`3HfG2b+0|r=T((-WP#1AHbChxHUAHfq~%$s2&LeRU3RPOe~B%;6*w@ zjG$o<CPp4cK1Lz%)DagW4<iqFN{IzD+|MY$#KkJY$OdCGae@0QT#N!tpvfkPY9UrO z#v+g%@YWS5GC>1D;F<}vToO_v)iPEJlt5}DrW(+yWX53d7HUR@Cg?OebeiA{tl$In z2Z~cmbU@ur(3T2N83S4#qL5hvntBD#13~AOz^y7s7Dg@oGUD^V3(Y{2+TivVXf3l9 zxcGx{p=BbdHv*bihL{5DcfgB6kYlVsi)CPCZ)yt6Zb%siDXBoQoeJrSgSGl;G8KUW z16+A)GT&l@I4Fv}pc34Mj$#Mt0JWsSF$N|;(RPamEDo}@IJHEDiGiUQwD^L7lY@x~ z+;(PTESdpo4}jW!poj&HMu1d+L;V4C;0jdR*D{qbWHDxe7FsZuu+=b@u-7nw*E60f z;b>;4WvP@X;jCfI;!0tZWJqBG)#)`X@!a7Id15RKB|O<&MPZOS4i-x_j9I)jEb+WG zELq$s%-KvuWnkSbk_<I0@t|R9?h^iN_M*NLff~jv!Ddh!fi;f<!meelkgH*JVTcv0 zWvgMVVUuL2WiJt`VF7g;Ygr2CgfrBzWC=Gj)N<4?WQo*pfa=mbp%PJW8-^1s#t9Ou z0d>h)6BR*iTFhD!7K6#9MWA&}pwZqu@OEcV6oY~lGM^0!TiAdGQV&D}S{0zCBjg;W zpn;@Z(+XCe!gC<p8n_MMqyVa0kVfDjV>;kL3dppZCNx<>l9LXGybj3R;)2YSRLCYN zka;i++S?8GSz=BOEL}q@UGQicxF?D_JPYmwYKj%vfQlMB5CK{Me2W#lK_Ut~tx}v? za*N#s;yTE%ENIOkxGz=Y1=0a77D4^aTO8i0mEZyqF$z)yTE$-kN|%sc<P?w&aNn&B z!~&&WO|Bx)B5CjxOcXbGFgG5&)+ve?6n4d+oyDNOK@>k^WfMGzqu4UQJB2|ssNqsH z9aKVc6qhD}ThLML#idCg6VMAokQ>ZEnF&-bF>rG+axwEUu`x1%)<ZFJFmW(}=F+(s z`M@j=5Y5QL0-F0Q0_oIbDl!3YF<=CTrzUez1c+M%8YR$#ieaUgz)C_iJ-}P^K)W~7 zN<jl}@$sNTFc^wJMP?DGonMpy3L4NbVia#dc6xkKDx|>!S<X-d>d@X|PAo1dVh7bN zta+um1(mm$@(Q9@Km{B)E~D5X)8fUDat9p#pw2=OsC2l+2I?G@7C<JA!JQLuEP*<~ z-~j>18aFO@N4B^~7;F<L7K)2NLmjucJ;A%e!Lc31T%1`^1g`nSKrRO_Oa-l(D>4Uh zEkJ}BC~8<zGIMf@su@80U6Ub4B|wH`L3`6~amU9)tL6B3@HSNNs#VC64A6?TTil_= zsYTFjOW?8FqM0D0K_jb0wjdTbVS-kdLKbu6fW$zP)!?a9@Pr+BoF6<&dy54$-~vg; zpnf#CYzEh1;35?q)kp~kQ6_WPKsMdlfxKA^s;F6*M8KsnXh8-CBL}ktqYM)dGpJ4l zEr(@el3?UuW?^Jwfrvmz5hhR>&c`Ug$i*hWCBP-XEx;+jBP1v!$fe6=#AVJQ$|b<X T%O%StDxl86#v#Dv!yyC!{UjO^ diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle_legacy.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle_legacy.cpython-36.pyc deleted file mode 100755 index e81a055331c0c861fbe8dbf300783bb85bcdd730..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14836 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 diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle_legacy2.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/hickle_legacy2.cpython-36.pyc deleted file mode 100755 index 477aa15d70a77296c4b1d4b98e55aa747dd6552f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20746 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 UCCnwn#ls~jpui>1VaLG-04tAcY5)KL diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/lookup.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/__pycache__/lookup.cpython-36.pyc deleted file mode 100644 index 6cd877598197f890a4cef46feab4f938a2529c61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6661 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 diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/helpers.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/helpers.py deleted file mode 100755 index 6c3d7f9f..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/helpers.py +++ /dev/null @@ -1,113 +0,0 @@ -import re -import six - -def get_type_and_data(h_node): - """ Helper function to return the py_type and data block for a HDF node """ - py_type = h_node.attrs["type"][0] - data = h_node[()] -# if h_node.shape == (): -# data = h_node.value -# else: -# data = h_node[:] - return py_type, data - -def get_type(h_node): - """ Helper function to return the py_type for a HDF node """ - py_type = h_node.attrs["type"][0] - return py_type - -def sort_keys(key_list): - """ Take a list of strings and sort it by integer value within string - - Args: - key_list (list): List of keys - - Returns: - key_list_sorted (list): List of keys, sorted by integer - """ - - # Py3 h5py returns an irritating KeysView object - # Py3 also complains about bytes and strings, convert all keys to bytes - if six.PY3: - key_list2 = [] - for key in key_list: - if isinstance(key, str): - key = bytes(key, 'ascii') - key_list2.append(key) - key_list = key_list2 - - # Check which keys contain a number - numbered_keys = [re.search(b'\d+', key) for key in key_list] - - # Sort the keys on number if they have it, or normally if not - if(len(key_list) and not numbered_keys.count(None)): - to_int = lambda x: int(re.search(b'\d+', x).group(0)) - return(sorted(key_list, key=to_int)) - else: - return(sorted(key_list)) - - -def check_is_iterable(py_obj): - """ Check whether a python object is iterable. - - Note: this treats unicode and string as NON ITERABLE - - Args: - py_obj: python object to test - - Returns: - iter_ok (bool): True if item is iterable, False is item is not - """ - if six.PY2: - string_types = (str, unicode) - else: - string_types = (str, bytes, bytearray) - if isinstance(py_obj, string_types): - return False - try: - iter(py_obj) - return True - except TypeError: - return False - - -def check_is_hashable(py_obj): - """ Check if a python object is hashable - - Note: this function is currently not used, but is useful for future - development. - - Args: - py_obj: python object to test - """ - - try: - py_obj.__hash__() - return True - except TypeError: - return False - - -def check_iterable_item_type(iter_obj): - """ Check if all items within an iterable are the same type. - - Args: - iter_obj: iterable object - - Returns: - iter_type: type of item contained within the iterable. If - the iterable has many types, a boolean False is returned instead. - - References: - http://stackoverflow.com/questions/13252333/python-check-if-all-elements-of-a-list-are-the-same-type - """ - iseq = iter(iter_obj) - - try: - first_type = type(next(iseq)) - except StopIteration: - return False - except Exception as ex: - return False - else: - return first_type if all((type(x) is first_type) for x in iseq) else False diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle.py deleted file mode 100755 index 24b38c3e..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle.py +++ /dev/null @@ -1,611 +0,0 @@ -# encoding: utf-8 -""" -# hickle.py - -Created by Danny Price 2016-02-03. - -Hickle is a HDF5 based clone of Pickle. Instead of serializing to a pickle -file, Hickle dumps to a HDF5 file. It is designed to be as similar to pickle in -usage as possible, providing a load() and dump() function. - -## Notes - -Hickle has two main advantages over Pickle: -1) LARGE PICKLE HANDLING. Unpickling a large pickle is slow, as the Unpickler -reads the entire pickle thing and loads it into memory. In comparison, HDF5 -files are designed for large datasets. Things are only loaded when accessed. - -2) CROSS PLATFORM SUPPORT. Attempting to unpickle a pickle pickled on Windows -on Linux and vice versa is likely to fail with errors like "Insecure string -pickle". HDF5 files will load fine, as long as both machines have -h5py installed. - -""" - -from __future__ import absolute_import, division, print_function -import sys -import os -from pkg_resources import get_distribution, DistributionNotFound -from ast import literal_eval - -import numpy as np -import h5py as h5 - - -from .helpers import get_type, sort_keys, check_is_iterable, check_iterable_item_type -from .lookup import types_dict, hkl_types_dict, types_not_to_sort, \ - container_types_dict, container_key_types_dict -from .lookup import check_is_ndarray_like - - -try: - from exceptions import Exception - from types import NoneType -except ImportError: - pass # above imports will fail in python3 - -from six import PY2, PY3, string_types, integer_types -import io - -# Make several aliases for Python2/Python3 compatibility -if PY3: - file = io.TextIOWrapper - -# Import a default 'pickler' -# Not the nicest import code, but should work on Py2/Py3 -try: - import dill as pickle -except ImportError: - try: - import cPickle as pickle - except ImportError: - import pickle - -import warnings - -try: - __version__ = get_distribution('hickle').version -except DistributionNotFound: - __version__ = '0.0.0 - please install via pip/setup.py' - -################## -# Error handling # -################## - -class FileError(Exception): - """ An exception raised if the file is fishy """ - def __init__(self): - return - - def __str__(self): - return ("Cannot open file. Please pass either a filename " - "string, a file object, or a h5py.File") - - -class ClosedFileError(Exception): - """ An exception raised if the file is fishy """ - def __init__(self): - return - - def __str__(self): - return ("HDF5 file has been closed. Please pass either " - "a filename string, a file object, or an open h5py.File") - - -class NoMatchError(Exception): - """ An exception raised if the object type is not understood (or - supported)""" - def __init__(self): - return - - def __str__(self): - return ("Error: this type of python object cannot be converted into a " - "hickle.") - - -class ToDoError(Exception): - """ An exception raised for non-implemented functionality""" - def __init__(self): - return - - def __str__(self): - return "Error: this functionality hasn't been implemented yet." - - -class SerializedWarning(UserWarning): - """ An object type was not understood - - The data will be serialized using pickle. - """ - pass - - -###################### -# H5PY file wrappers # -###################### - -class H5GroupWrapper(h5.Group): - """ Group wrapper that provides a track_times kwarg. - - track_times is a boolean flag that can be set to False, so that two - files created at different times will have identical MD5 hashes. - """ - def create_dataset(self, *args, **kwargs): - kwargs['track_times'] = getattr(self, 'track_times', True) - return super(H5GroupWrapper, self).create_dataset(*args, **kwargs) - - def create_group(self, *args, **kwargs): - group = super(H5GroupWrapper, self).create_group(*args, **kwargs) - group.__class__ = H5GroupWrapper - group.track_times = getattr(self, 'track_times', True) - return group - - -class H5FileWrapper(h5.File): - """ Wrapper for h5py File that provides a track_times kwarg. - - track_times is a boolean flag that can be set to False, so that two - files created at different times will have identical MD5 hashes. - """ - def create_dataset(self, *args, **kwargs): - kwargs['track_times'] = getattr(self, 'track_times', True) - return super(H5FileWrapper, self).create_dataset(*args, **kwargs) - - def create_group(self, *args, **kwargs): - group = super(H5FileWrapper, self).create_group(*args, **kwargs) - group.__class__ = H5GroupWrapper - group.track_times = getattr(self, 'track_times', True) - return group - - -def file_opener(f, mode='r', track_times=True): - """ A file opener helper function with some error handling. This can open - files through a file object, a h5py file, or just the filename. - - Args: - f (file, h5py.File, or string): File-identifier, e.g. filename or file object. - mode (str): File open mode. Only required if opening by filename string. - track_times (bool): Track time in HDF5; turn off if you want hickling at - different times to produce identical files (e.g. for MD5 hash check). - - """ - - # Assume that we will have to close the file after dump or load - close_flag = True - - # Were we handed a file object or just a file name string? - if isinstance(f, (file, io.TextIOWrapper)): - filename, mode = f.name, f.mode - f.close() - h5f = h5.File(filename, mode) - elif isinstance(f, string_types): - filename = f - h5f = h5.File(filename, mode) - elif isinstance(f, (H5FileWrapper, h5._hl.files.File)): - try: - filename = f.filename - except ValueError: - raise ClosedFileError - h5f = f - # Since this file was already open, do not close the file afterward - close_flag = False - else: - print(f.__class__) - raise FileError - - h5f.__class__ = H5FileWrapper - h5f.track_times = track_times - return(h5f, close_flag) - - -########### -# DUMPERS # -########### - - -def _dump(py_obj, h_group, call_id=0, **kwargs): - """ Dump a python object to a group within a HDF5 file. - - This function is called recursively by the main dump() function. - - Args: - py_obj: python object to dump. - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - - # Get list of dumpable dtypes - dumpable_dtypes = [] - for lst in [[bool, complex, bytes, float], string_types, integer_types]: - dumpable_dtypes.extend(lst) - - # Firstly, check if item is a numpy array. If so, just dump it. - if check_is_ndarray_like(py_obj): - create_hkl_dataset(py_obj, h_group, call_id, **kwargs) - - # Next, check if item is a dict - elif isinstance(py_obj, dict): - create_hkl_dataset(py_obj, h_group, call_id, **kwargs) - - # If not, check if item is iterable - elif check_is_iterable(py_obj): - item_type = check_iterable_item_type(py_obj) - - # item_type == False implies multiple types. Create a dataset - if item_type is False: - h_subgroup = create_hkl_group(py_obj, h_group, call_id) - for ii, py_subobj in enumerate(py_obj): - _dump(py_subobj, h_subgroup, call_id=ii, **kwargs) - - # otherwise, subitems have same type. Check if subtype is an iterable - # (e.g. list of lists), or not (e.g. list of ints, which should be treated - # as a single dataset). - else: - if item_type in dumpable_dtypes: - create_hkl_dataset(py_obj, h_group, call_id, **kwargs) - else: - h_subgroup = create_hkl_group(py_obj, h_group, call_id) - for ii, py_subobj in enumerate(py_obj): - _dump(py_subobj, h_subgroup, call_id=ii, **kwargs) - - # item is not iterable, so create a dataset for it - else: - create_hkl_dataset(py_obj, h_group, call_id, **kwargs) - - -def dump(py_obj, file_obj, mode='w', track_times=True, path='/', **kwargs): - """ Write a pickled representation of obj to the open file object file. - - Args: - obj (object): python object o store in a Hickle - file: file object, filename string, or h5py.File object - file in which to store the object. A h5py.File or a filename is also - acceptable. - mode (str): optional argument, 'r' (read only), 'w' (write) or 'a' (append). - Ignored if file is a file object. - compression (str): optional argument. Applies compression to dataset. Options: None, gzip, - lzf (+ szip, if installed) - track_times (bool): optional argument. If set to False, repeated hickling will produce - identical files. - path (str): path within hdf5 file to save data to. Defaults to root / - """ - - # Make sure that file is not closed unless modified - # This is to avoid trying to close a file that was never opened - close_flag = False - - try: - # Open the file - h5f, close_flag = file_opener(file_obj, mode, track_times) - h5f.attrs["CLASS"] = b'hickle' - h5f.attrs["VERSION"] = get_distribution('hickle').version - h5f.attrs["type"] = [b'hickle'] - # Log which version of python was used to generate the hickle file - pv = sys.version_info - py_ver = "%i.%i.%i" % (pv[0], pv[1], pv[2]) - h5f.attrs["PYTHON_VERSION"] = py_ver - - h_root_group = h5f.get(path) - - if h_root_group is None: - h_root_group = h5f.create_group(path) - h_root_group.attrs["type"] = [b'hickle'] - - _dump(py_obj, h_root_group, **kwargs) - except NoMatchError: - fname = h5f.filename - h5f.close() - try: - os.remove(fname) - except OSError: - warnings.warn("Dump failed. Could not remove %s" % fname) - finally: - raise NoMatchError - finally: - # Close the file if requested. - # Closing a file twice will not cause any problems - if close_flag: - h5f.close() - - -def create_dataset_lookup(py_obj): - """ What type of object are we trying to pickle? This is a python - dictionary based equivalent of a case statement. It returns the correct - helper function for a given data type. - - Args: - py_obj: python object to look-up what function to use to dump to disk - - Returns: - match: function that should be used to dump data to a new dataset - """ - t = type(py_obj) - types_lookup = {dict: create_dict_dataset} - types_lookup.update(types_dict) - - match = types_lookup.get(t, no_match) - - return match - - - -def create_hkl_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Create a dataset within the hickle HDF5 file - - Args: - py_obj: python object to dump. - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - - """ - #lookup dataset creator type based on python object type - create_dataset = create_dataset_lookup(py_obj) - - # do the creation - create_dataset(py_obj, h_group, call_id, **kwargs) - - -def create_hkl_group(py_obj, h_group, call_id=0): - """ Create a new group within the hickle file - - Args: - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - - """ - h_subgroup = h_group.create_group('data_%i' % call_id) - h_subgroup.attrs['type'] = [str(type(py_obj)).encode('ascii', 'ignore')] - return h_subgroup - - -def create_dict_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Creates a data group for each key in dictionary - - Notes: - This is a very important function which uses the recursive _dump - method to build up hierarchical data models stored in the HDF5 file. - As this is critical to functioning, it is kept in the main hickle.py - file instead of in the loaders/ directory. - - Args: - py_obj: python object to dump; should be dictionary - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - h_dictgroup = h_group.create_group('data_%i' % call_id) - h_dictgroup.attrs['type'] = [str(type(py_obj)).encode('ascii', 'ignore')] - - for key, py_subobj in py_obj.items(): - if isinstance(key, string_types): - h_subgroup = h_dictgroup.create_group("%r" % (key)) - else: - h_subgroup = h_dictgroup.create_group(str(key)) - h_subgroup.attrs["type"] = [b'dict_item'] - - h_subgroup.attrs["key_type"] = [str(type(key)).encode('ascii', 'ignore')] - - _dump(py_subobj, h_subgroup, call_id=0, **kwargs) - - -def no_match(py_obj, h_group, call_id=0, **kwargs): - """ If no match is made, raise an exception - - Args: - py_obj: python object to dump; default if item is not matched. - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - pickled_obj = pickle.dumps(py_obj) - d = h_group.create_dataset('data_%i' % call_id, data=[pickled_obj]) - d.attrs["type"] = [b'pickle'] - - warnings.warn("%s type not understood, data have been serialized" % type(py_obj), - SerializedWarning) - - - -############# -## LOADERS ## -############# - -class PyContainer(list): - """ A group-like object into which to load datasets. - - In order to build up a tree-like structure, we need to be able - to load datasets into a container with an append() method. - Python tuples and sets do not allow this. This class provides - a list-like object that be converted into a list, tuple, set or dict. - """ - def __init__(self): - super(PyContainer, self).__init__() - self.container_type = None - self.name = None - self.key_type = None - - def convert(self): - """ Convert from PyContainer to python core data type. - - Returns: self, either as a list, tuple, set or dict - (or other type specified in lookup.py) - """ - - if self.container_type in container_types_dict.keys(): - convert_fn = container_types_dict[self.container_type] - return convert_fn(self) - if self.container_type == str(dict).encode('ascii', 'ignore'): - keys = [] - for item in self: - key = item.name.split('/')[-1] - key_type = item.key_type[0] - if key_type in container_key_types_dict.keys(): - to_type_fn = container_key_types_dict[key_type] - key = to_type_fn(key) - keys.append(key) - - items = [item[0] for item in self] - return dict(zip(keys, items)) - else: - return self - -def no_match_load(key): - """ If no match is made when loading, need to raise an exception - """ - raise RuntimeError("Cannot load %s data type" % key) - #pass - -def load_dataset_lookup(key): - """ What type of object are we trying to unpickle? This is a python - dictionary based equivalent of a case statement. It returns the type - a given 'type' keyword in the hickle file. - - Args: - py_obj: python object to look-up what function to use to dump to disk - - Returns: - match: function that should be used to dump data to a new dataset - """ - - match = hkl_types_dict.get(key, no_match_load) - - return match - -def load(fileobj, path='/', safe=True): - """ Load a hickle file and reconstruct a python object - - Args: - fileobj: file object, h5py.File, or filename string - safe (bool): Disable automatic depickling of arbitrary python objects. - DO NOT set this to False unless the file is from a trusted source. - (see http://www.cs.jhu.edu/~s/musings/pickle.html for an explanation) - - path (str): path within hdf5 file to save data to. Defaults to root / - """ - - # Make sure that the file is not closed unless modified - # This is to avoid trying to close a file that was never opened - close_flag = False - - try: - h5f, close_flag = file_opener(fileobj) - h_root_group = h5f.get(path) - try: - assert 'CLASS' in h5f.attrs.keys() - assert 'VERSION' in h5f.attrs.keys() - VER = h5f.attrs['VERSION'] - try: - VER_MAJOR = int(VER) - except ValueError: - VER_MAJOR = int(VER[0]) - if VER_MAJOR == 1: - if PY2: - warnings.warn("Hickle file versioned as V1, attempting legacy loading...") - from . import hickle_legacy - return hickle_legacy.load(fileobj, safe) - else: - raise RuntimeError("Cannot open file. This file was likely" - " created with Python 2 and an old hickle version.") - elif VER_MAJOR == 2: - if PY2: - warnings.warn("Hickle file appears to be old version (v2), attempting " - "legacy loading...") - from . import hickle_legacy2 - return hickle_legacy2.load(fileobj, path=path, safe=safe) - else: - raise RuntimeError("Cannot open file. This file was likely" - " created with Python 2 and an old hickle version.") - # There is an unfortunate period of time where hickle 2.1.0 claims VERSION = int(3) - # For backward compatibility we really need to catch this. - # Actual hickle v3 files are versioned as A.B.C (e.g. 3.1.0) - elif VER_MAJOR == 3 and VER == VER_MAJOR: - if PY2: - warnings.warn("Hickle file appears to be old version (v2.1.0), attempting " - "legacy loading...") - from . import hickle_legacy2 - return hickle_legacy2.load(fileobj, path=path, safe=safe) - else: - raise RuntimeError("Cannot open file. This file was likely" - " created with Python 2 and an old hickle version.") - elif VER_MAJOR >= 3: - py_container = PyContainer() - py_container.container_type = 'hickle' - py_container = _load(py_container, h_root_group) - return py_container[0][0] - - except AssertionError: - if PY2: - warnings.warn("Hickle file is not versioned, attempting legacy loading...") - from . import hickle_legacy - return hickle_legacy.load(fileobj, safe) - else: - raise RuntimeError("Cannot open file. This file was likely" - " created with Python 2 and an old hickle version.") - finally: - # Close the file if requested. - # Closing a file twice will not cause any problems - if close_flag: - h5f.close() - -def load_dataset(h_node): - """ Load a dataset, converting into its correct python type - - Args: - h_node (h5py dataset): h5py dataset object to read - - Returns: - data: reconstructed python object from loaded data - """ - py_type = get_type(h_node) - - try: - load_fn = load_dataset_lookup(py_type) - return load_fn(h_node) - except: - raise - #raise RuntimeError("Hickle type %s not understood." % py_type) - -def _load(py_container, h_group): - """ Load a hickle file - - Recursive funnction to load hdf5 data into a PyContainer() - - Args: - py_container (PyContainer): Python container to load data into - h_group (h5 group or dataset): h5py object, group or dataset, to spider - and load all datasets. - """ - - group_dtype = h5._hl.group.Group - dataset_dtype = h5._hl.dataset.Dataset - - #either a file, group, or dataset - if isinstance(h_group, (H5FileWrapper, group_dtype)): - - py_subcontainer = PyContainer() - try: - py_subcontainer.container_type = bytes(h_group.attrs['type'][0]) - except KeyError: - raise - #py_subcontainer.container_type = '' - py_subcontainer.name = h_group.name - - if py_subcontainer.container_type == b'dict_item': - py_subcontainer.key_type = h_group.attrs['key_type'] - - if py_subcontainer.container_type not in types_not_to_sort: - h_keys = sort_keys(h_group.keys()) - else: - h_keys = h_group.keys() - - for h_name in h_keys: - h_node = h_group[h_name] - py_subcontainer = _load(py_subcontainer, h_node) - - sub_data = py_subcontainer.convert() - py_container.append(sub_data) - - else: - # must be a dataset - subdata = load_dataset(h_group) - py_container.append(subdata) - - return py_container diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy.py deleted file mode 100755 index 61a171fd..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy.py +++ /dev/null @@ -1,535 +0,0 @@ -# encoding: utf-8 -""" -# hickle_legacy.py - -Created by Danny Price 2012-05-28. - -Hickle is a HDF5 based clone of Pickle. Instead of serializing to a -pickle file, Hickle dumps to a HDF5 file. It is designed to be as similar -to pickle in usage as possible. - -## Notes - -This is a legacy handler, for hickle v1 files. -If V2 reading fails, this will be called as a fail-over. - -""" - -import os -import sys -import numpy as np -import h5py as h5 - -if sys.version_info.major == 3: - NoneType = type(None) -else: - from types import NoneType - -__version__ = "1.3.0" -__author__ = "Danny Price" - -#################### -## Error handling ## -#################### - - -class FileError(Exception): - """ An exception raised if the file is fishy""" - - def __init__(self): - return - - def __str__(self): - print("Error: cannot open file. Please pass either a filename string, a file object, " - "or a h5py.File") - - -class NoMatchError(Exception): - """ An exception raised if the object type is not understood (or supported)""" - - def __init__(self): - return - - def __str__(self): - print("Error: this type of python object cannot be converted into a hickle.") - - -class ToDoError(Exception): - """ An exception raised for non-implemented functionality""" - - def __init__(self): - return - - def __str__(self): - print("Error: this functionality hasn't been implemented yet.") - - -class H5GroupWrapper(h5.Group): - def create_dataset(self, *args, **kwargs): - kwargs['track_times'] = getattr(self, 'track_times', True) - return super(H5GroupWrapper, self).create_dataset(*args, **kwargs) - - def create_group(self, *args, **kwargs): - group = super(H5GroupWrapper, self).create_group(*args, **kwargs) - group.__class__ = H5GroupWrapper - group.track_times = getattr(self, 'track_times', True) - return group - - -class H5FileWrapper(h5.File): - def create_dataset(self, *args, **kwargs): - kwargs['track_times'] = getattr(self, 'track_times', True) - return super(H5FileWrapper, self).create_dataset(*args, **kwargs) - - def create_group(self, *args, **kwargs): - group = super(H5FileWrapper, self).create_group(*args, **kwargs) - group.__class__ = H5GroupWrapper - group.track_times = getattr(self, 'track_times', True) - return group - - -def file_opener(f, mode='r', track_times=True): - """ A file opener helper function with some error handling. - - This can open files through a file object, a h5py file, or just the filename. - """ - # Were we handed a file object or just a file name string? - if isinstance(f, file): - filename, mode = f.name, f.mode - f.close() - h5f = h5.File(filename, mode) - - elif isinstance(f, h5._hl.files.File): - h5f = f - elif isinstance(f, str): - filename = f - h5f = h5.File(filename, mode) - else: - raise FileError - - h5f.__class__ = H5FileWrapper - h5f.track_times = track_times - return h5f - - -############# -## dumpers ## -############# - -def dump_ndarray(obj, h5f, **kwargs): - """ dumps an ndarray object to h5py file""" - h5f.create_dataset('data', data=obj, **kwargs) - h5f.create_dataset('type', data=['ndarray']) - - -def dump_np_dtype(obj, h5f, **kwargs): - """ dumps an np dtype object to h5py file""" - h5f.create_dataset('data', data=obj) - h5f.create_dataset('type', data=['np_dtype']) - - -def dump_np_dtype_dict(obj, h5f, **kwargs): - """ dumps an np dtype object within a group""" - h5f.create_dataset('data', data=obj) - h5f.create_dataset('_data', data=['np_dtype']) - - -def dump_masked(obj, h5f, **kwargs): - """ dumps an ndarray object to h5py file""" - h5f.create_dataset('data', data=obj, **kwargs) - h5f.create_dataset('mask', data=obj.mask, **kwargs) - h5f.create_dataset('type', data=['masked']) - - -def dump_list(obj, h5f, **kwargs): - """ dumps a list object to h5py file""" - - # Check if there are any numpy arrays in the list - contains_numpy = any(isinstance(el, np.ndarray) for el in obj) - - if contains_numpy: - _dump_list_np(obj, h5f, **kwargs) - else: - h5f.create_dataset('data', data=obj, **kwargs) - h5f.create_dataset('type', data=['list']) - - -def _dump_list_np(obj, h5f, **kwargs): - """ Dump a list of numpy objects to file """ - - np_group = h5f.create_group('data') - h5f.create_dataset('type', data=['np_list']) - - ii = 0 - for np_item in obj: - np_group.create_dataset("%s" % ii, data=np_item, **kwargs) - ii += 1 - - -def dump_tuple(obj, h5f, **kwargs): - """ dumps a list object to h5py file""" - - # Check if there are any numpy arrays in the list - contains_numpy = any(isinstance(el, np.ndarray) for el in obj) - - if contains_numpy: - _dump_tuple_np(obj, h5f, **kwargs) - else: - h5f.create_dataset('data', data=obj, **kwargs) - h5f.create_dataset('type', data=['tuple']) - - -def _dump_tuple_np(obj, h5f, **kwargs): - """ Dump a tuple of numpy objects to file """ - - np_group = h5f.create_group('data') - h5f.create_dataset('type', data=['np_tuple']) - - ii = 0 - for np_item in obj: - np_group.create_dataset("%s" % ii, data=np_item, **kwargs) - ii += 1 - - -def dump_set(obj, h5f, **kwargs): - """ dumps a set object to h5py file""" - obj = list(obj) - h5f.create_dataset('data', data=obj, **kwargs) - h5f.create_dataset('type', data=['set']) - - -def dump_string(obj, h5f, **kwargs): - """ dumps a list object to h5py file""" - h5f.create_dataset('data', data=[obj], **kwargs) - h5f.create_dataset('type', data=['string']) - - -def dump_none(obj, h5f, **kwargs): - """ Dump None type to file """ - h5f.create_dataset('data', data=[0], **kwargs) - h5f.create_dataset('type', data=['none']) - - -def dump_unicode(obj, h5f, **kwargs): - """ dumps a list object to h5py file""" - dt = h5.special_dtype(vlen=unicode) - ll = len(obj) - dset = h5f.create_dataset('data', shape=(ll, ), dtype=dt, **kwargs) - dset[:ll] = obj - h5f.create_dataset('type', data=['unicode']) - - -def _dump_dict(dd, hgroup, **kwargs): - for key in dd: - if type(dd[key]) in (str, int, float, unicode, bool): - # Figure out type to be stored - types = {str: 'str', int: 'int', float: 'float', - unicode: 'unicode', bool: 'bool', NoneType: 'none'} - _key = types.get(type(dd[key])) - - # Store along with dtype info - if _key == 'unicode': - dd[key] = str(dd[key]) - - hgroup.create_dataset("%s" % key, data=[dd[key]], **kwargs) - hgroup.create_dataset("_%s" % key, data=[_key]) - - elif type(dd[key]) in (type(np.array([1])), type(np.ma.array([1]))): - - if hasattr(dd[key], 'mask'): - hgroup.create_dataset("_%s" % key, data=["masked"]) - hgroup.create_dataset("%s" % key, data=dd[key].data, **kwargs) - hgroup.create_dataset("_%s_mask" % key, data=dd[key].mask, **kwargs) - else: - hgroup.create_dataset("_%s" % key, data=["ndarray"]) - hgroup.create_dataset("%s" % key, data=dd[key], **kwargs) - - elif type(dd[key]) is list: - hgroup.create_dataset("%s" % key, data=dd[key], **kwargs) - hgroup.create_dataset("_%s" % key, data=["list"]) - - elif type(dd[key]) is tuple: - hgroup.create_dataset("%s" % key, data=dd[key], **kwargs) - hgroup.create_dataset("_%s" % key, data=["tuple"]) - - elif type(dd[key]) is set: - hgroup.create_dataset("%s" % key, data=list(dd[key]), **kwargs) - hgroup.create_dataset("_%s" % key, data=["set"]) - - elif isinstance(dd[key], dict): - new_group = hgroup.create_group("%s" % key) - _dump_dict(dd[key], new_group, **kwargs) - - elif type(dd[key]) is NoneType: - hgroup.create_dataset("%s" % key, data=[0], **kwargs) - hgroup.create_dataset("_%s" % key, data=["none"]) - - else: - if type(dd[key]).__module__ == np.__name__: - #print type(dd[key]) - hgroup.create_dataset("%s" % key, data=dd[key]) - hgroup.create_dataset("_%s" % key, data=["np_dtype"]) - #new_group = hgroup.create_group("%s" % key) - #dump_np_dtype_dict(dd[key], new_group) - else: - raise NoMatchError - - -def dump_dict(obj, h5f='', **kwargs): - """ dumps a dictionary to h5py file """ - h5f.create_dataset('type', data=['dict']) - hgroup = h5f.create_group('data') - _dump_dict(obj, hgroup, **kwargs) - - -def no_match(obj, h5f, *args, **kwargs): - """ If no match is made, raise an exception """ - try: - import dill as cPickle - except ImportError: - import cPickle - - pickled_obj = cPickle.dumps(obj) - h5f.create_dataset('type', data=['pickle']) - h5f.create_dataset('data', data=[pickled_obj]) - - print("Warning: %s type not understood, data have been serialized" % type(obj)) - #raise NoMatchError - - -def dumper_lookup(obj): - """ What type of object are we trying to pickle? - - This is a python dictionary based equivalent of a case statement. - It returns the correct helper function for a given data type. - """ - t = type(obj) - - types = { - list: dump_list, - tuple: dump_tuple, - set: dump_set, - dict: dump_dict, - str: dump_string, - unicode: dump_unicode, - NoneType: dump_none, - np.ndarray: dump_ndarray, - np.ma.core.MaskedArray: dump_masked, - np.float16: dump_np_dtype, - np.float32: dump_np_dtype, - np.float64: dump_np_dtype, - np.int8: dump_np_dtype, - np.int16: dump_np_dtype, - np.int32: dump_np_dtype, - np.int64: dump_np_dtype, - np.uint8: dump_np_dtype, - np.uint16: dump_np_dtype, - np.uint32: dump_np_dtype, - np.uint64: dump_np_dtype, - np.complex64: dump_np_dtype, - np.complex128: dump_np_dtype, - } - - match = types.get(t, no_match) - return match - - -def dump(obj, file, mode='w', track_times=True, **kwargs): - """ Write a pickled representation of obj to the open file object file. - - Parameters - ---------- - obj: object - python object o store in a Hickle - file: file object, filename string, or h5py.File object - file in which to store the object. A h5py.File or a filename is also acceptable. - mode: string - optional argument, 'r' (read only), 'w' (write) or 'a' (append). Ignored if file - is a file object. - compression: str - optional argument. Applies compression to dataset. Options: None, gzip, lzf (+ szip, - if installed) - track_times: bool - optional argument. If set to False, repeated hickling will produce identical files. - """ - - try: - # See what kind of object to dump - dumper = dumper_lookup(obj) - # Open the file - h5f = file_opener(file, mode, track_times) - print("dumping %s to file %s" % (type(obj), repr(h5f))) - dumper(obj, h5f, **kwargs) - h5f.close() - except NoMatchError: - fname = h5f.filename - h5f.close() - try: - os.remove(fname) - except: - print("Warning: dump failed. Could not remove %s" % fname) - finally: - raise NoMatchError - - -############# -## loaders ## -############# - -def load(file, safe=True): - """ Load a hickle file and reconstruct a python object - - Parameters - ---------- - file: file object, h5py.File, or filename string - - safe (bool): Disable automatic depickling of arbitrary python objects. - DO NOT set this to False unless the file is from a trusted source. - (see http://www.cs.jhu.edu/~s/musings/pickle.html for an explanation) - """ - - try: - h5f = file_opener(file) - dtype = h5f["type"][0] - - if dtype == 'dict': - group = h5f["data"] - data = load_dict(group) - elif dtype == 'pickle': - data = load_pickle(h5f, safe) - elif dtype == 'np_list': - group = h5f["data"] - data = load_np_list(group) - elif dtype == 'np_tuple': - group = h5f["data"] - data = load_np_tuple(group) - elif dtype == 'masked': - data = np.ma.array(h5f["data"][:], mask=h5f["mask"][:]) - elif dtype == 'none': - data = None - else: - if dtype in ('string', 'unicode'): - data = h5f["data"][0] - else: - try: - data = h5f["data"][:] - except ValueError: - data = h5f["data"] - types = { - 'list': list, - 'set': set, - 'unicode': unicode, - 'string': str, - 'ndarray': load_ndarray, - 'np_dtype': load_np_dtype - } - - mod = types.get(dtype, no_match) - data = mod(data) - finally: - if 'h5f' in locals(): - h5f.close() - return data - - -def load_pickle(h5f, safe=True): - """ Deserialize and load a pickled object within a hickle file - - WARNING: Pickle has - - Parameters - ---------- - h5f: h5py.File object - - safe (bool): Disable automatic depickling of arbitrary python objects. - DO NOT set this to False unless the file is from a trusted source. - (see http://www.cs.jhu.edu/~s/musings/pickle.html for an explanation) - """ - - if not safe: - try: - import dill as cPickle - except ImportError: - import cPickle - - data = h5f["data"][:] - data = cPickle.loads(data[0]) - return data - else: - print("\nWarning: Object is of an unknown type, and has not been loaded") - print(" for security reasons (it could be malicious code). If") - print(" you wish to continue, manually set safe=False\n") - - -def load_np_list(group): - """ load a numpy list """ - np_list = [] - for key in sorted(group.keys()): - data = group[key][:] - np_list.append(data) - return np_list - - -def load_np_tuple(group): - """ load a tuple containing numpy arrays """ - return tuple(load_np_list(group)) - - -def load_ndarray(arr): - """ Load a numpy array """ - # Nothing to be done! - return arr - - -def load_np_dtype(arr): - """ Load a numpy array """ - # Just return first value - return arr.value - - -def load_dict(group): - """ Load dictionary """ - - dd = {} - for key in group.keys(): - if isinstance(group[key], h5._hl.group.Group): - new_group = group[key] - dd[key] = load_dict(new_group) - elif not key.startswith("_"): - _key = "_%s" % key - - if group[_key][0] == 'np_dtype': - dd[key] = group[key].value - elif group[_key][0] in ('str', 'int', 'float', 'unicode', 'bool'): - dd[key] = group[key][0] - elif group[_key][0] == 'masked': - key_ma = "_%s_mask" % key - dd[key] = np.ma.array(group[key][:], mask=group[key_ma]) - else: - dd[key] = group[key][:] - - # Convert numpy constructs back to string - dtype = group[_key][0] - types = {'str': str, 'int': int, 'float': float, - 'unicode': unicode, 'bool': bool, 'list': list, 'none' : NoneType} - try: - mod = types.get(dtype) - if dtype == 'none': - dd[key] = None - else: - dd[key] = mod(dd[key]) - except: - pass - return dd - - -def load_large(file): - """ Load a large hickle file (returns the h5py object not the data) - - Parameters - ---------- - file: file object, h5py.File, or filename string - """ - - h5f = file_opener(file) - return h5f diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy2.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy2.py deleted file mode 100755 index 4d018fde..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/hickle_legacy2.py +++ /dev/null @@ -1,672 +0,0 @@ -# encoding: utf-8 -""" -# hickle_legacy2.py - -Created by Danny Price 2016-02-03. - -This is a legacy handler, for hickle v2 files. -If V3 reading fails, this will be called as a fail-over. - -""" - -import os -import numpy as np -import h5py as h5 -import re - -try: - from exceptions import Exception - from types import NoneType -except ImportError: - pass # above imports will fail in python3 - -import warnings -__version__ = "2.0.4" -__author__ = "Danny Price" - - -################## -# Error handling # -################## - -class FileError(Exception): - """ An exception raised if the file is fishy """ - def __init__(self): - return - - def __str__(self): - return ("Cannot open file. Please pass either a filename " - "string, a file object, or a h5py.File") - - -class ClosedFileError(Exception): - """ An exception raised if the file is fishy """ - def __init__(self): - return - - def __str__(self): - return ("HDF5 file has been closed. Please pass either " - "a filename string, a file object, or an open h5py.File") - - -class NoMatchError(Exception): - """ An exception raised if the object type is not understood (or - supported)""" - def __init__(self): - return - - def __str__(self): - return ("Error: this type of python object cannot be converted into a " - "hickle.") - - -class ToDoError(Exception): - """ An exception raised for non-implemented functionality""" - def __init__(self): - return - - def __str__(self): - return "Error: this functionality hasn't been implemented yet." - - -###################### -# H5PY file wrappers # -###################### - -class H5GroupWrapper(h5.Group): - """ Group wrapper that provides a track_times kwarg. - - track_times is a boolean flag that can be set to False, so that two - files created at different times will have identical MD5 hashes. - """ - def create_dataset(self, *args, **kwargs): - kwargs['track_times'] = getattr(self, 'track_times', True) - return super(H5GroupWrapper, self).create_dataset(*args, **kwargs) - - def create_group(self, *args, **kwargs): - group = super(H5GroupWrapper, self).create_group(*args, **kwargs) - group.__class__ = H5GroupWrapper - group.track_times = getattr(self, 'track_times', True) - return group - - -class H5FileWrapper(h5.File): - """ Wrapper for h5py File that provides a track_times kwarg. - - track_times is a boolean flag that can be set to False, so that two - files created at different times will have identical MD5 hashes. - """ - def create_dataset(self, *args, **kwargs): - kwargs['track_times'] = getattr(self, 'track_times', True) - return super(H5FileWrapper, self).create_dataset(*args, **kwargs) - - def create_group(self, *args, **kwargs): - group = super(H5FileWrapper, self).create_group(*args, **kwargs) - group.__class__ = H5GroupWrapper - group.track_times = getattr(self, 'track_times', True) - return group - - -def file_opener(f, mode='r', track_times=True): - """ A file opener helper function with some error handling. This can open - files through a file object, a h5py file, or just the filename. - - Args: - f (file, h5py.File, or string): File-identifier, e.g. filename or file object. - mode (str): File open mode. Only required if opening by filename string. - track_times (bool): Track time in HDF5; turn off if you want hickling at - different times to produce identical files (e.g. for MD5 hash check). - - """ - # Were we handed a file object or just a file name string? - if isinstance(f, file): - filename, mode = f.name, f.mode - f.close() - h5f = h5.File(filename, mode) - elif isinstance(f, str) or isinstance(f, unicode): - filename = f - h5f = h5.File(filename, mode) - elif isinstance(f, H5FileWrapper) or isinstance(f, h5._hl.files.File): - try: - filename = f.filename - except ValueError: - raise ClosedFileError() - h5f = f - else: - print(type(f)) - raise FileError - - h5f.__class__ = H5FileWrapper - h5f.track_times = track_times - return h5f - - -########### -# DUMPERS # -########### - -def check_is_iterable(py_obj): - """ Check whether a python object is iterable. - - Note: this treats unicode and string as NON ITERABLE - - Args: - py_obj: python object to test - - Returns: - iter_ok (bool): True if item is iterable, False is item is not - """ - if type(py_obj) in (str, unicode): - return False - try: - iter(py_obj) - return True - except TypeError: - return False - - -def check_iterable_item_type(iter_obj): - """ Check if all items within an iterable are the same type. - - Args: - iter_obj: iterable object - - Returns: - iter_type: type of item contained within the iterable. If - the iterable has many types, a boolean False is returned instead. - - References: - http://stackoverflow.com/questions/13252333/python-check-if-all-elements-of-a-list-are-the-same-type - """ - iseq = iter(iter_obj) - first_type = type(next(iseq)) - return first_type if all((type(x) is first_type) for x in iseq) else False - - -def check_is_numpy_array(py_obj): - """ Check if a python object is a numpy array (masked or regular) - - Args: - py_obj: python object to check whether it is a numpy array - - Returns - is_numpy (bool): Returns True if it is a numpy array, else False if it isn't - """ - - is_numpy = type(py_obj) in (type(np.array([1])), type(np.ma.array([1]))) - - return is_numpy - - -def _dump(py_obj, h_group, call_id=0, **kwargs): - """ Dump a python object to a group within a HDF5 file. - - This function is called recursively by the main dump() function. - - Args: - py_obj: python object to dump. - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - - dumpable_dtypes = set([bool, int, float, long, complex, str, unicode]) - - # Firstly, check if item is a numpy array. If so, just dump it. - if check_is_numpy_array(py_obj): - create_hkl_dataset(py_obj, h_group, call_id, **kwargs) - - # next, check if item is iterable - elif check_is_iterable(py_obj): - item_type = check_iterable_item_type(py_obj) - - # item_type == False implies multiple types. Create a dataset - if item_type is False: - h_subgroup = create_hkl_group(py_obj, h_group, call_id) - for ii, py_subobj in enumerate(py_obj): - _dump(py_subobj, h_subgroup, call_id=ii, **kwargs) - - # otherwise, subitems have same type. Check if subtype is an iterable - # (e.g. list of lists), or not (e.g. list of ints, which should be treated - # as a single dataset). - else: - if item_type in dumpable_dtypes: - create_hkl_dataset(py_obj, h_group, call_id, **kwargs) - else: - h_subgroup = create_hkl_group(py_obj, h_group, call_id) - for ii, py_subobj in enumerate(py_obj): - #print py_subobj, h_subgroup, ii - _dump(py_subobj, h_subgroup, call_id=ii, **kwargs) - - # item is not iterable, so create a dataset for it - else: - create_hkl_dataset(py_obj, h_group, call_id, **kwargs) - - -def dump(py_obj, file_obj, mode='w', track_times=True, path='/', **kwargs): - """ Write a pickled representation of obj to the open file object file. - - Args: - obj (object): python object o store in a Hickle - file: file object, filename string, or h5py.File object - file in which to store the object. A h5py.File or a filename is also - acceptable. - mode (str): optional argument, 'r' (read only), 'w' (write) or 'a' (append). - Ignored if file is a file object. - compression (str): optional argument. Applies compression to dataset. Options: None, gzip, - lzf (+ szip, if installed) - track_times (bool): optional argument. If set to False, repeated hickling will produce - identical files. - path (str): path within hdf5 file to save data to. Defaults to root / - """ - - try: - # Open the file - h5f = file_opener(file_obj, mode, track_times) - h5f.attrs["CLASS"] = 'hickle' - h5f.attrs["VERSION"] = 2 - h5f.attrs["type"] = ['hickle'] - - h_root_group = h5f.get(path) - - if h_root_group is None: - h_root_group = h5f.create_group(path) - h_root_group.attrs["type"] = ['hickle'] - - _dump(py_obj, h_root_group, **kwargs) - h5f.close() - except NoMatchError: - fname = h5f.filename - h5f.close() - try: - os.remove(fname) - except OSError: - warnings.warn("Dump failed. Could not remove %s" % fname) - finally: - raise NoMatchError - - -def create_dataset_lookup(py_obj): - """ What type of object are we trying to pickle? This is a python - dictionary based equivalent of a case statement. It returns the correct - helper function for a given data type. - - Args: - py_obj: python object to look-up what function to use to dump to disk - - Returns: - match: function that should be used to dump data to a new dataset - """ - t = type(py_obj) - - types = { - dict: create_dict_dataset, - list: create_listlike_dataset, - tuple: create_listlike_dataset, - set: create_listlike_dataset, - str: create_stringlike_dataset, - unicode: create_stringlike_dataset, - int: create_python_dtype_dataset, - float: create_python_dtype_dataset, - long: create_python_dtype_dataset, - bool: create_python_dtype_dataset, - complex: create_python_dtype_dataset, - NoneType: create_none_dataset, - np.ndarray: create_np_array_dataset, - np.ma.core.MaskedArray: create_np_array_dataset, - np.float16: create_np_dtype_dataset, - np.float32: create_np_dtype_dataset, - np.float64: create_np_dtype_dataset, - np.int8: create_np_dtype_dataset, - np.int16: create_np_dtype_dataset, - np.int32: create_np_dtype_dataset, - np.int64: create_np_dtype_dataset, - np.uint8: create_np_dtype_dataset, - np.uint16: create_np_dtype_dataset, - np.uint32: create_np_dtype_dataset, - np.uint64: create_np_dtype_dataset, - np.complex64: create_np_dtype_dataset, - np.complex128: create_np_dtype_dataset - } - - match = types.get(t, no_match) - return match - - -def create_hkl_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Create a dataset within the hickle HDF5 file - - Args: - py_obj: python object to dump. - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - - """ - #lookup dataset creator type based on python object type - create_dataset = create_dataset_lookup(py_obj) - - # do the creation - create_dataset(py_obj, h_group, call_id, **kwargs) - - -def create_hkl_group(py_obj, h_group, call_id=0): - """ Create a new group within the hickle file - - Args: - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - - """ - h_subgroup = h_group.create_group('data_%i' % call_id) - h_subgroup.attrs["type"] = [str(type(py_obj))] - return h_subgroup - - -def create_listlike_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Dumper for list, set, tuple - - Args: - py_obj: python object to dump; should be list-like - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - dtype = str(type(py_obj)) - obj = list(py_obj) - d = h_group.create_dataset('data_%i' % call_id, data=obj, **kwargs) - d.attrs["type"] = [dtype] - - -def create_np_dtype_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps an np dtype object to h5py file - - Args: - py_obj: python object to dump; should be a numpy scalar, e.g. np.float16(1) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, **kwargs) - d.attrs["type"] = ['np_dtype'] - d.attrs["np_dtype"] = str(d.dtype) - - -def create_python_dtype_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps a python dtype object to h5py file - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, - dtype=type(py_obj), **kwargs) - d.attrs["type"] = ['python_dtype'] - d.attrs['python_subdtype'] = str(type(py_obj)) - - -def create_dict_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Creates a data group for each key in dictionary - - Args: - py_obj: python object to dump; should be dictionary - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - h_dictgroup = h_group.create_group('data_%i' % call_id) - h_dictgroup.attrs["type"] = ['dict'] - for key, py_subobj in py_obj.items(): - h_subgroup = h_dictgroup.create_group(key) - h_subgroup.attrs["type"] = ['dict_item'] - _dump(py_subobj, h_subgroup, call_id=0, **kwargs) - - -def create_np_array_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps an ndarray object to h5py file - - Args: - py_obj: python object to dump; should be a numpy array or np.ma.array (masked) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - if isinstance(py_obj, type(np.ma.array([1]))): - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, **kwargs) - #m = h_group.create_dataset('mask_%i' % call_id, data=py_obj.mask, **kwargs) - m = h_group.create_dataset('data_%i_mask' % call_id, data=py_obj.mask, **kwargs) - d.attrs["type"] = ['ndarray_masked_data'] - m.attrs["type"] = ['ndarray_masked_mask'] - else: - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, **kwargs) - d.attrs["type"] = ['ndarray'] - - -def create_stringlike_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps a list object to h5py file - - Args: - py_obj: python object to dump; should be string-like (unicode or string) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - if isinstance(py_obj, str): - d = h_group.create_dataset('data_%i' % call_id, data=[py_obj], **kwargs) - d.attrs["type"] = ['string'] - else: - dt = h5.special_dtype(vlen=unicode) - dset = h_group.create_dataset('data_%i' % call_id, shape=(1, ), dtype=dt, **kwargs) - dset[0] = py_obj - dset.attrs['type'] = ['unicode'] - - -def create_none_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Dump None type to file - - Args: - py_obj: python object to dump; must be None object - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - d = h_group.create_dataset('data_%i' % call_id, data=[0], **kwargs) - d.attrs["type"] = ['none'] - - -def no_match(py_obj, h_group, call_id=0, **kwargs): - """ If no match is made, raise an exception - - Args: - py_obj: python object to dump; default if item is not matched. - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - try: - import dill as cPickle - except ImportError: - import cPickle - - pickled_obj = cPickle.dumps(py_obj) - d = h_group.create_dataset('data_%i' % call_id, data=[pickled_obj]) - d.attrs["type"] = ['pickle'] - - warnings.warn("%s type not understood, data have been " - "serialized" % type(py_obj)) - - -############# -## LOADERS ## -############# - -class PyContainer(list): - """ A group-like object into which to load datasets. - - In order to build up a tree-like structure, we need to be able - to load datasets into a container with an append() method. - Python tuples and sets do not allow this. This class provides - a list-like object that be converted into a list, tuple, set or dict. - """ - def __init__(self): - super(PyContainer, self).__init__() - self.container_type = None - self.name = None - - def convert(self): - """ Convert from PyContainer to python core data type. - - Returns: self, either as a list, tuple, set or dict - """ - if self.container_type == "<type 'list'>": - return list(self) - if self.container_type == "<type 'tuple'>": - return tuple(self) - if self.container_type == "<type 'set'>": - return set(self) - if self.container_type == "dict": - keys = [str(item.name.split('/')[-1]) for item in self] - items = [item[0] for item in self] - return dict(zip(keys, items)) - else: - return self - - -def load(fileobj, path='/', safe=True): - """ Load a hickle file and reconstruct a python object - - Args: - fileobj: file object, h5py.File, or filename string - safe (bool): Disable automatic depickling of arbitrary python objects. - DO NOT set this to False unless the file is from a trusted source. - (see http://www.cs.jhu.edu/~s/musings/pickle.html for an explanation) - - path (str): path within hdf5 file to save data to. Defaults to root / - """ - - try: - h5f = file_opener(fileobj) - h_root_group = h5f.get(path) - - try: - assert 'CLASS' in h5f.attrs.keys() - assert 'VERSION' in h5f.attrs.keys() - py_container = PyContainer() - py_container.container_type = 'hickle' - py_container = _load(py_container, h_root_group) - return py_container[0][0] - except AssertionError: - import hickle_legacy - return hickle_legacy.load(fileobj, safe) - finally: - if 'h5f' in locals(): - h5f.close() - - -def load_dataset(h_node): - """ Load a dataset, converting into its correct python type - - Args: - h_node (h5py dataset): h5py dataset object to read - - Returns: - data: reconstructed python object from loaded data - """ - py_type = h_node.attrs["type"][0] - - if h_node.shape == (): - data = h_node.value - else: - data = h_node[:] - - if py_type == "<type 'list'>": - #print self.name - return list(data) - elif py_type == "<type 'tuple'>": - return tuple(data) - elif py_type == "<type 'set'>": - return set(data) - elif py_type == "np_dtype": - subtype = h_node.attrs["np_dtype"] - data = np.array(data, dtype=subtype) - return data - elif py_type == 'ndarray': - return np.array(data) - elif py_type == 'ndarray_masked_data': - try: - mask_path = h_node.name + "_mask" - h_root = h_node.parent - mask = h_root.get(mask_path)[:] - except IndexError: - mask = h_root.get(mask_path) - except ValueError: - mask = h_root.get(mask_path) - data = np.ma.array(data, mask=mask) - return data - elif py_type == 'python_dtype': - subtype = h_node.attrs["python_subdtype"] - type_dict = { - "<type 'int'>": int, - "<type 'float'>": float, - "<type 'long'>": long, - "<type 'bool'>": bool, - "<type 'complex'>": complex - } - tcast = type_dict.get(subtype) - return tcast(data) - elif py_type == 'string': - return str(data[0]) - elif py_type == 'unicode': - return unicode(data[0]) - elif py_type == 'none': - return None - else: - print(h_node.name, py_type, h_node.attrs.keys()) - return data - - -def sort_keys(key_list): - """ Take a list of strings and sort it by integer value within string - - Args: - key_list (list): List of keys - - Returns: - key_list_sorted (list): List of keys, sorted by integer - """ - to_int = lambda x: int(re.search('\d+', x).group(0)) - keys_by_int = sorted([(to_int(key), key) for key in key_list]) - return [ii[1] for ii in keys_by_int] - - -def _load(py_container, h_group): - """ Load a hickle file - - Recursive funnction to load hdf5 data into a PyContainer() - - Args: - py_container (PyContainer): Python container to load data into - h_group (h5 group or dataset): h5py object, group or dataset, to spider - and load all datasets. - """ - - group_dtype = h5._hl.group.Group - dataset_dtype = h5._hl.dataset.Dataset - - #either a file, group, or dataset - if isinstance(h_group, H5FileWrapper) or isinstance(h_group, group_dtype): - py_subcontainer = PyContainer() - py_subcontainer.container_type = h_group.attrs['type'][0] - py_subcontainer.name = h_group.name - - if py_subcontainer.container_type != 'dict': - h_keys = sort_keys(h_group.keys()) - else: - h_keys = h_group.keys() - - for h_name in h_keys: - h_node = h_group[h_name] - py_subcontainer = _load(py_subcontainer, h_node) - - sub_data = py_subcontainer.convert() - py_container.append(sub_data) - - else: - # must be a dataset - subdata = load_dataset(h_group) - py_container.append(subdata) - - #print h_group.name, py_container - return py_container diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__init__.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__init__.py deleted file mode 100755 index 3be6bd29..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import absolute_import \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/__init__.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/__init__.cpython-36.pyc deleted file mode 100644 index 059bbcb18d24b4ed243c011342d5220fc0ca9b4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 252 zcmXr!<>i`^S{<v#z`*dB0SPcMFfceUFfbGgFfcHrFr+Z%Fyt~uF)}iwFa<McGQR{V z)nvTIpO{pfpHo_r8lRb4kY7~dr^$4SD?UE0w4}5sH9o!wWXwv2A{GV)2=S|2zd*mB zC_gJTxkNuXE2}u!#7I9WGcR2~H%GTPwJfzLGfzJwGdVjaRX-;)Nxz`7BqKl1SkFwq zII|>Gw;(Y&J25@A7^+0qSkFYySht|kSkFu^H9Z|Fte=ygn37sltREkrnU`4-AFo$X Ud5gm)H$SB`C)JJ-<SUT#0mmCgmH+?% diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_astropy.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_astropy.cpython-36.pyc deleted file mode 100644 index 3856511eb477a1bd3a48b33dd2325efe9afb4735..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7453 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 diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_numpy.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_numpy.cpython-36.pyc deleted file mode 100644 index 0b431b401afea544b1894a3b08b282d070c988e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4199 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 S9IPB{94s8X94t(XFbDu|4<v8^ diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_pandas.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_pandas.cpython-36.pyc deleted file mode 100644 index 2df2075b66902547e8435e4a81eba6a175408411..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249 zcmXr!<>i`^S{>`hz`*dB0SPcMFfceUFfbGgFfcHrFr+Z%Fhnt?Gej|^Fa|SdGQ9*T z_0wdIVk=0@OGzxg#Z-`Ti!V7RvA8(CC^bE^xFoe`B|{Ml0|SKkRi$5`Ur>~vm6}|l zpPZFdoNQvGpOl%GuAiHuTbx>!T9lcmpOKlIos+7clbNJnP+5|ZpJ%LRreB;{lB!#f zn4F!Mo>~l5qHC;YqGzmIP-(1Zrk9$Y4i(nV$xlp4Eh+}n@eqgU6;$5hu*uC&Da}c> MV+45!<TDOt0Q#v$)c^nh diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_python.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_python.cpython-36.pyc deleted file mode 100755 index ada924cd472a1993704ccdda86ab632d87e62aa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4349 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 RWai*wVZ?+SERbk}kN}LkDqR2o diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_python3.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_python3.cpython-36.pyc deleted file mode 100644 index 53f514453416469ddfd6d8843477414904a3276f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5988 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 b@NlreAu|UjhX4yB6f!|+MjjSW^dm3;w1JAU diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_scipy.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/__pycache__/load_scipy.cpython-36.pyc deleted file mode 100644 index aff088cfb6e7c7c16bc2fd5a3ae5dd05f77bdd41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3032 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 Z1i6$rL_w_yF=iHKE=Dd!P(*Ms0svE~7pDLK diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_astropy.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_astropy.py deleted file mode 100755 index dd8efce6..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_astropy.py +++ /dev/null @@ -1,237 +0,0 @@ -import numpy as np -from astropy.units import Quantity -from astropy.coordinates import Angle, SkyCoord -from astropy.constants import Constant, EMConstant -from astropy.table import Table -from astropy.time import Time - -from hickle.helpers import get_type_and_data -import six - -def create_astropy_quantity(py_obj, h_group, call_id=0, **kwargs): - """ dumps an astropy quantity - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - # kwarg compression etc does not work on scalars - d = h_group.create_dataset('data_%i' % call_id, data=py_obj.value, - dtype='float64') #, **kwargs) - d.attrs["type"] = [b'astropy_quantity'] - if six.PY3: - unit = bytes(str(py_obj.unit), 'ascii') - else: - unit = str(py_obj.unit) - d.attrs['unit'] = [unit] - -def create_astropy_angle(py_obj, h_group, call_id=0, **kwargs): - """ dumps an astropy quantity - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - # kwarg compression etc does not work on scalars - d = h_group.create_dataset('data_%i' % call_id, data=py_obj.value, - dtype='float64') #, **kwargs) - d.attrs["type"] = [b'astropy_angle'] - if six.PY3: - unit = str(py_obj.unit).encode('ascii') - else: - unit = str(py_obj.unit) - d.attrs['unit'] = [unit] - -def create_astropy_skycoord(py_obj, h_group, call_id=0, **kwargs): - """ dumps an astropy quantity - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - # kwarg compression etc does not work on scalars - lat = py_obj.data.lat.value - lon = py_obj.data.lon.value - dd = np.column_stack((lon, lat)) - - d = h_group.create_dataset('data_%i' % call_id, data=dd, - dtype='float64') #, **kwargs) - d.attrs["type"] = [b'astropy_skycoord'] - if six.PY3: - lon_unit = str(py_obj.data.lon.unit).encode('ascii') - lat_unit = str(py_obj.data.lat.unit).encode('ascii') - else: - lon_unit = str(py_obj.data.lon.unit) - lat_unit = str(py_obj.data.lat.unit) - d.attrs['lon_unit'] = [lon_unit] - d.attrs['lat_unit'] = [lat_unit] - -def create_astropy_time(py_obj, h_group, call_id=0, **kwargs): - """ dumps an astropy Time object - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - - # kwarg compression etc does not work on scalars - data = py_obj.value - dtype = str(py_obj.value.dtype) - - # Need to catch string times - if '<U' in dtype: - dtype = dtype.replace('<U', '|S') - print(dtype) - data = [] - for item in py_obj.value: - data.append(str(item).encode('ascii')) - - d = h_group.create_dataset('data_%i' % call_id, data=data, dtype=dtype) #, **kwargs) - d.attrs["type"] = [b'astropy_time'] - if six.PY2: - fmt = str(py_obj.format) - scale = str(py_obj.scale) - else: - fmt = str(py_obj.format).encode('ascii') - scale = str(py_obj.scale).encode('ascii') - d.attrs['format'] = [fmt] - d.attrs['scale'] = [scale] - -def create_astropy_constant(py_obj, h_group, call_id=0, **kwargs): - """ dumps an astropy constant - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - # kwarg compression etc does not work on scalars - d = h_group.create_dataset('data_%i' % call_id, data=py_obj.value, - dtype='float64') #, **kwargs) - d.attrs["type"] = [b'astropy_constant'] - d.attrs["unit"] = [str(py_obj.unit)] - d.attrs["abbrev"] = [str(py_obj.abbrev)] - d.attrs["name"] = [str(py_obj.name)] - d.attrs["reference"] = [str(py_obj.reference)] - d.attrs["uncertainty"] = [py_obj.uncertainty] - - if py_obj.system: - d.attrs["system"] = [py_obj.system] - - -def create_astropy_table(py_obj, h_group, call_id=0, **kwargs): - """ Dump an astropy Table - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - data = py_obj.as_array() - d = h_group.create_dataset('data_%i' % call_id, data=data, dtype=data.dtype, **kwargs) - d.attrs['type'] = [b'astropy_table'] - - if six.PY3: - colnames = [bytes(cn, 'ascii') for cn in py_obj.colnames] - else: - colnames = py_obj.colnames - d.attrs['colnames'] = colnames - for key, value in py_obj.meta.items(): - d.attrs[key] = value - - -def load_astropy_quantity_dataset(h_node): - py_type, data = get_type_and_data(h_node) - unit = h_node.attrs["unit"][0] - q = Quantity(data, unit) - return q - -def load_astropy_time_dataset(h_node): - py_type, data = get_type_and_data(h_node) - if six.PY3: - fmt = h_node.attrs["format"][0].decode('ascii') - scale = h_node.attrs["scale"][0].decode('ascii') - else: - fmt = h_node.attrs["format"][0] - scale = h_node.attrs["scale"][0] - q = Time(data, format=fmt, scale=scale) - return q - -def load_astropy_angle_dataset(h_node): - py_type, data = get_type_and_data(h_node) - unit = h_node.attrs["unit"][0] - q = Angle(data, unit) - return q - -def load_astropy_skycoord_dataset(h_node): - py_type, data = get_type_and_data(h_node) - lon_unit = h_node.attrs["lon_unit"][0] - lat_unit = h_node.attrs["lat_unit"][0] - q = SkyCoord(data[:,0], data[:, 1], unit=(lon_unit, lat_unit)) - return q - -def load_astropy_constant_dataset(h_node): - py_type, data = get_type_and_data(h_node) - unit = h_node.attrs["unit"][0] - abbrev = h_node.attrs["abbrev"][0] - name = h_node.attrs["name"][0] - ref = h_node.attrs["reference"][0] - unc = h_node.attrs["uncertainty"][0] - - system = None - if "system" in h_node.attrs.keys(): - system = h_node.attrs["system"][0] - - c = Constant(abbrev, name, data, unit, unc, ref, system) - return c - -def load_astropy_table(h_node): - py_type, data = get_type_and_data(h_node) - metadata = dict(h_node.attrs.items()) - metadata.pop('type') - metadata.pop('colnames') - - if six.PY3: - colnames = [cn.decode('ascii') for cn in h_node.attrs["colnames"]] - else: - colnames = h_node.attrs["colnames"] - - t = Table(data, names=colnames, meta=metadata) - return t - -def check_is_astropy_table(py_obj): - return isinstance(py_obj, Table) - -def check_is_astropy_quantity_array(py_obj): - if isinstance(py_obj, Quantity) or isinstance(py_obj, Time) or \ - isinstance(py_obj, Angle) or isinstance(py_obj, SkyCoord): - if py_obj.isscalar: - return False - else: - return True - else: - return False - - -##################### -# Lookup dictionary # -##################### - -class_register = [ - [Quantity, b'astropy_quantity', create_astropy_quantity, load_astropy_quantity_dataset, - True, check_is_astropy_quantity_array], - [Time, b'astropy_time', create_astropy_time, load_astropy_time_dataset, - True, check_is_astropy_quantity_array], - [Angle, b'astropy_angle', create_astropy_angle, load_astropy_angle_dataset, - True, check_is_astropy_quantity_array], - [SkyCoord, b'astropy_skycoord', create_astropy_skycoord, load_astropy_skycoord_dataset, - True, check_is_astropy_quantity_array], - [Constant, b'astropy_constant', create_astropy_constant, load_astropy_constant_dataset, - True, None], - [Table, b'astropy_table', create_astropy_table, load_astropy_table, - True, check_is_astropy_table] -] diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_numpy.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_numpy.py deleted file mode 100755 index 7a31b12e..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_numpy.py +++ /dev/null @@ -1,145 +0,0 @@ -# encoding: utf-8 -""" -# load_numpy.py - -Utilities and dump / load handlers for handling numpy and scipy arrays - -""" -import six -import numpy as np - - -from hickle.helpers import get_type_and_data - - -def check_is_numpy_array(py_obj): - """ Check if a python object is a numpy array (masked or regular) - - Args: - py_obj: python object to check whether it is a numpy array - - Returns - is_numpy (bool): Returns True if it is a numpy array, else False if it isn't - """ - - is_numpy = type(py_obj) in (type(np.array([1])), type(np.ma.array([1]))) - - return is_numpy - - -def create_np_scalar_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps an np dtype object to h5py file - - Args: - py_obj: python object to dump; should be a numpy scalar, e.g. np.float16(1) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - - # DO NOT PASS KWARGS TO SCALAR DATASETS! - d = h_group.create_dataset('data_%i' % call_id, data=py_obj) # **kwargs) - d.attrs["type"] = [b'np_scalar'] - - if six.PY2: - d.attrs["np_dtype"] = str(d.dtype) - else: - d.attrs["np_dtype"] = bytes(str(d.dtype), 'ascii') - - -def create_np_dtype(py_obj, h_group, call_id=0, **kwargs): - """ dumps an np dtype object to h5py file - - Args: - py_obj: python object to dump; should be a numpy scalar, e.g. np.float16(1) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - d = h_group.create_dataset('data_%i' % call_id, data=[str(py_obj)]) - d.attrs["type"] = [b'np_dtype'] - - -def create_np_array_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps an ndarray object to h5py file - - Args: - py_obj: python object to dump; should be a numpy array or np.ma.array (masked) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - if isinstance(py_obj, type(np.ma.array([1]))): - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, **kwargs) - #m = h_group.create_dataset('mask_%i' % call_id, data=py_obj.mask, **kwargs) - m = h_group.create_dataset('data_%i_mask' % call_id, data=py_obj.mask, **kwargs) - d.attrs["type"] = [b'ndarray_masked_data'] - m.attrs["type"] = [b'ndarray_masked_mask'] - else: - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, **kwargs) - d.attrs["type"] = [b'ndarray'] - - - - -####################### -## Lookup dictionary ## -####################### - -types_dict = { - np.ndarray: create_np_array_dataset, - np.ma.core.MaskedArray: create_np_array_dataset, - np.float16: create_np_scalar_dataset, - np.float32: create_np_scalar_dataset, - np.float64: create_np_scalar_dataset, - np.int8: create_np_scalar_dataset, - np.int16: create_np_scalar_dataset, - np.int32: create_np_scalar_dataset, - np.int64: create_np_scalar_dataset, - np.uint8: create_np_scalar_dataset, - np.uint16: create_np_scalar_dataset, - np.uint32: create_np_scalar_dataset, - np.uint64: create_np_scalar_dataset, - np.complex64: create_np_scalar_dataset, - np.complex128: create_np_scalar_dataset, - np.dtype: create_np_dtype -} - -def load_np_dtype_dataset(h_node): - py_type, data = get_type_and_data(h_node) - data = np.dtype(data[0]) - return data - -def load_np_scalar_dataset(h_node): - py_type, data = get_type_and_data(h_node) - subtype = h_node.attrs["np_dtype"] - data = np.array([data], dtype=subtype)[0] - return data - -def load_ndarray_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return np.array(data, copy=False) - -def load_ndarray_masked_dataset(h_node): - py_type, data = get_type_and_data(h_node) - try: - mask_path = h_node.name + "_mask" - h_root = h_node.parent - mask = h_root.get(mask_path)[:] - except IndexError: - mask = h_root.get(mask_path) - except ValueError: - mask = h_root.get(mask_path) - data = np.ma.array(data, mask=mask) - return data - -def load_nothing(h_hode): - pass - -hkl_types_dict = { - b"np_dtype" : load_np_dtype_dataset, - b"np_scalar" : load_np_scalar_dataset, - b"ndarray" : load_ndarray_dataset, - b"numpy.ndarray" : load_ndarray_dataset, - b"ndarray_masked_data" : load_ndarray_masked_dataset, - b"ndarray_masked_mask" : load_nothing # Loaded autormatically -} - - diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_pandas.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_pandas.py deleted file mode 100755 index 0b518553..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_pandas.py +++ /dev/null @@ -1,4 +0,0 @@ -import pandas as pd - -# TODO: populate with classes to load -class_register = [] \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python.py deleted file mode 100755 index 58de921e..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python.py +++ /dev/null @@ -1,141 +0,0 @@ -# encoding: utf-8 -""" -# load_python.py - -Handlers for dumping and loading built-in python types. -NB: As these are for built-in types, they are critical to the functioning of hickle. - -""" - -from hickle.helpers import get_type_and_data - -import sys -if sys.version_info.major == 3: - unicode = type(str) - str = type(bytes) - long = type(int) - NoneType = type(None) -else: - from types import NoneType - -import h5py as h5 - -def create_listlike_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Dumper for list, set, tuple - - Args: - py_obj: python object to dump; should be list-like - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - dtype = str(type(py_obj)) - obj = list(py_obj) - d = h_group.create_dataset('data_%i' % call_id, data=obj, **kwargs) - d.attrs["type"] = [dtype] - - -def create_python_dtype_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps a python dtype object to h5py file - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - # kwarg compression etc does not work on scalars - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, - dtype=type(py_obj)) #, **kwargs) - d.attrs["type"] = ['python_dtype'] - d.attrs['python_subdtype'] = str(type(py_obj)) - - -def create_stringlike_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps a list object to h5py file - - Args: - py_obj: python object to dump; should be string-like (unicode or string) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - if isinstance(py_obj, str): - d = h_group.create_dataset('data_%i' % call_id, data=[py_obj], **kwargs) - d.attrs["type"] = ['string'] - else: - dt = h5.special_dtype(vlen=unicode) - dset = h_group.create_dataset('data_%i' % call_id, shape=(1, ), dtype=dt, **kwargs) - dset[0] = py_obj - dset.attrs['type'] = ['unicode'] - - -def create_none_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Dump None type to file - - Args: - py_obj: python object to dump; must be None object - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - d = h_group.create_dataset('data_%i' % call_id, data=[0], **kwargs) - d.attrs["type"] = ['none'] - - -def load_list_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return list(data) - -def load_tuple_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return tuple(data) - -def load_set_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return set(data) - -def load_string_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return str(data[0]) - -def load_unicode_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return unicode(data[0]) - -def load_none_dataset(h_node): - return None - -def load_python_dtype_dataset(h_node): - py_type, data = get_type_and_data(h_node) - subtype = h_node.attrs["python_subdtype"] - type_dict = { - "<type 'int'>": int, - "<type 'float'>": float, - "<type 'long'>": long, - "<type 'bool'>": bool, - "<type 'complex'>": complex - } - tcast = type_dict.get(subtype) - return tcast(data) - -types_dict = { - list: create_listlike_dataset, - tuple: create_listlike_dataset, - set: create_listlike_dataset, - str: create_stringlike_dataset, - unicode: create_stringlike_dataset, - int: create_python_dtype_dataset, - float: create_python_dtype_dataset, - long: create_python_dtype_dataset, - bool: create_python_dtype_dataset, - complex: create_python_dtype_dataset, - NoneType: create_none_dataset, -} - -hkl_types_dict = { - "<type 'list'>" : load_list_dataset, - "<type 'tuple'>" : load_tuple_dataset, - "<type 'set'>" : load_set_dataset, - "python_dtype" : load_python_dtype_dataset, - "string" : load_string_dataset, - "unicode" : load_unicode_dataset, - "none" : load_none_dataset -} - diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python3.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python3.py deleted file mode 100755 index c6b173fd..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_python3.py +++ /dev/null @@ -1,201 +0,0 @@ -# encoding: utf-8 -""" -# load_python.py - -Handlers for dumping and loading built-in python types. -NB: As these are for built-in types, they are critical to the functioning of hickle. - -""" - -import six -from hickle.helpers import get_type_and_data - -try: - from exceptions import Exception -except ImportError: - pass # above imports will fail in python3 - -try: - ModuleNotFoundError # This fails on Py3.5 and below -except NameError: - ModuleNotFoundError = ImportError - -import h5py as h5 - - -def get_py3_string_type(h_node): - """ Helper function to return the python string type for items in a list. - - Notes: - Py3 string handling is a bit funky and doesn't play too nicely with HDF5. - We needed to add metadata to say if the strings in a list started off as - bytes, string, etc. This helper loads - - """ - try: - py_type = h_node.attrs["py3_string_type"][0] - return py_type - except: - return None - -def create_listlike_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Dumper for list, set, tuple - - Args: - py_obj: python object to dump; should be list-like - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - dtype = str(type(py_obj)) - obj = list(py_obj) - - # h5py does not handle Py3 'str' objects well. Need to catch this - # Only need to check first element as this method - # is only called if all elements have same dtype - py3_str_type = None - if type(obj[0]) in (str, bytes): - py3_str_type = bytes(str(type(obj[0])), 'ascii') - - if type(obj[0]) is str: - #print(py3_str_type) - #print(obj, "HERE") - obj = [bytes(oo, 'utf8') for oo in obj] - #print(obj, "HERE") - - - d = h_group.create_dataset('data_%i' % call_id, data=obj, **kwargs) - d.attrs["type"] = [bytes(dtype, 'ascii')] - - # Need to add some metadata to aid in unpickling if it's a string type - if py3_str_type is not None: - d.attrs["py3_string_type"] = [py3_str_type] - - - -def create_python_dtype_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps a python dtype object to h5py file - - Args: - py_obj: python object to dump; should be a python type (int, float, bool etc) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - # kwarg compression etc does not work on scalars - d = h_group.create_dataset('data_%i' % call_id, data=py_obj, - dtype=type(py_obj)) #, **kwargs) - d.attrs["type"] = [b'python_dtype'] - d.attrs['python_subdtype'] = bytes(str(type(py_obj)), 'ascii') - - -def create_stringlike_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps a list object to h5py file - - Args: - py_obj: python object to dump; should be string-like (unicode or string) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - if isinstance(py_obj, bytes): - d = h_group.create_dataset('data_%i' % call_id, data=[py_obj], **kwargs) - d.attrs["type"] = [b'bytes'] - elif isinstance(py_obj, str): - dt = h5.special_dtype(vlen=str) - dset = h_group.create_dataset('data_%i' % call_id, shape=(1, ), dtype=dt, **kwargs) - dset[0] = py_obj - dset.attrs['type'] = [b'string'] - -def create_none_dataset(py_obj, h_group, call_id=0, **kwargs): - """ Dump None type to file - - Args: - py_obj: python object to dump; must be None object - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - d = h_group.create_dataset('data_%i' % call_id, data=[0], **kwargs) - d.attrs["type"] = [b'none'] - - -def load_list_dataset(h_node): - py_type, data = get_type_and_data(h_node) - py3_str_type = get_py3_string_type(h_node) - - if py3_str_type == b"<class 'bytes'>": - # Yuck. Convert numpy._bytes -> str -> bytes - return [bytes(str(item, 'utf8'), 'utf8') for item in data] - if py3_str_type == b"<class 'str'>": - return [str(item, 'utf8') for item in data] - else: - return list(data) - -def load_tuple_dataset(h_node): - data = load_list_dataset(h_node) - return tuple(data) - -def load_set_dataset(h_node): - data = load_list_dataset(h_node) - return set(data) - -def load_bytes_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return bytes(data[0]) - -def load_string_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return str(data[0]) - -def load_unicode_dataset(h_node): - py_type, data = get_type_and_data(h_node) - return unicode(data[0]) - -def load_none_dataset(h_node): - return None - -def load_pickled_data(h_node): - py_type, data = get_type_and_data(h_node) - try: - import cPickle as pickle - except ModuleNotFoundError: - import pickle - return pickle.loads(data[0]) - - -def load_python_dtype_dataset(h_node): - py_type, data = get_type_and_data(h_node) - subtype = h_node.attrs["python_subdtype"] - type_dict = { - b"<class 'int'>": int, - b"<class 'float'>": float, - b"<class 'bool'>": bool, - b"<class 'complex'>": complex - } - - tcast = type_dict.get(subtype) - return tcast(data) - - - -types_dict = { - list: create_listlike_dataset, - tuple: create_listlike_dataset, - set: create_listlike_dataset, - bytes: create_stringlike_dataset, - str: create_stringlike_dataset, - #bytearray: create_stringlike_dataset, - int: create_python_dtype_dataset, - float: create_python_dtype_dataset, - bool: create_python_dtype_dataset, - complex: create_python_dtype_dataset, - type(None): create_none_dataset, -} - -hkl_types_dict = { - b"<class 'list'>" : load_list_dataset, - b"<class 'tuple'>" : load_tuple_dataset, - b"<class 'set'>" : load_set_dataset, - b"bytes" : load_bytes_dataset, - b"python_dtype" : load_python_dtype_dataset, - b"string" : load_string_dataset, - b"pickle" : load_pickled_data, - b"none" : load_none_dataset, -} diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_scipy.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_scipy.py deleted file mode 100755 index ab09fe23..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/loaders/load_scipy.py +++ /dev/null @@ -1,92 +0,0 @@ -import six -import scipy -from scipy import sparse - -from hickle.helpers import get_type_and_data - -def check_is_scipy_sparse_array(py_obj): - """ Check if a python object is a scipy sparse array - - Args: - py_obj: python object to check whether it is a sparse array - - Returns - is_numpy (bool): Returns True if it is a sparse array, else False if it isn't - """ - t_csr = type(scipy.sparse.csr_matrix([0])) - t_csc = type(scipy.sparse.csc_matrix([0])) - t_bsr = type(scipy.sparse.bsr_matrix([0])) - is_sparse = type(py_obj) in (t_csr, t_csc, t_bsr) - - return is_sparse - - -def create_sparse_dataset(py_obj, h_group, call_id=0, **kwargs): - """ dumps an sparse array to h5py file - - Args: - py_obj: python object to dump; should be a numpy array or np.ma.array (masked) - h_group (h5.File.group): group to dump data into. - call_id (int): index to identify object's relative location in the iterable. - """ - h_sparsegroup = h_group.create_group('data_%i' % call_id) - data = h_sparsegroup.create_dataset('data', data=py_obj.data, **kwargs) - indices = h_sparsegroup.create_dataset('indices', data=py_obj.indices, **kwargs) - indptr = h_sparsegroup.create_dataset('indptr', data=py_obj.indptr, **kwargs) - shape = h_sparsegroup.create_dataset('shape', data=py_obj.shape, **kwargs) - - if isinstance(py_obj, type(sparse.csr_matrix([0]))): - type_str = 'csr' - elif isinstance(py_obj, type(sparse.csc_matrix([0]))): - type_str = 'csc' - elif isinstance(py_obj, type(sparse.bsr_matrix([0]))): - type_str = 'bsr' - - if six.PY2: - h_sparsegroup.attrs["type"] = [b'%s_matrix' % type_str] - data.attrs["type"] = [b"%s_matrix_data" % type_str] - indices.attrs["type"] = [b"%s_matrix_indices" % type_str] - indptr.attrs["type"] = [b"%s_matrix_indptr" % type_str] - shape.attrs["type"] = [b"%s_matrix_shape" % type_str] - else: - h_sparsegroup.attrs["type"] = [bytes(str('%s_matrix' % type_str), 'ascii')] - data.attrs["type"] = [bytes(str("%s_matrix_data" % type_str), 'ascii')] - indices.attrs["type"] = [bytes(str("%s_matrix_indices" % type_str), 'ascii')] - indptr.attrs["type"] = [bytes(str("%s_matrix_indptr" % type_str), 'ascii')] - shape.attrs["type"] = [bytes(str("%s_matrix_shape" % type_str), 'ascii')] - -def load_sparse_matrix_data(h_node): - - py_type, data = get_type_and_data(h_node) - h_root = h_node.parent - indices = h_root.get('indices')[:] - indptr = h_root.get('indptr')[:] - shape = h_root.get('shape')[:] - - if py_type == b'csc_matrix_data': - smat = sparse.csc_matrix((data, indices, indptr), dtype=data.dtype, shape=shape) - elif py_type == b'csr_matrix_data': - smat = sparse.csr_matrix((data, indices, indptr), dtype=data.dtype, shape=shape) - elif py_type == b'bsr_matrix_data': - smat = sparse.bsr_matrix((data, indices, indptr), dtype=data.dtype, shape=shape) - return smat - - - - - -class_register = [ - [scipy.sparse.csr_matrix, b'csr_matrix_data', create_sparse_dataset, load_sparse_matrix_data, False, check_is_scipy_sparse_array], - [scipy.sparse.csc_matrix, b'csc_matrix_data', create_sparse_dataset, load_sparse_matrix_data, False, check_is_scipy_sparse_array], - [scipy.sparse.bsr_matrix, b'bsr_matrix_data', create_sparse_dataset, load_sparse_matrix_data, False, check_is_scipy_sparse_array], -] - -exclude_register = [] - -# Need to ignore things like csc_matrix_indices which are loaded automatically -for mat_type in ('csr', 'csc', 'bsr'): - for attrib in ('indices', 'indptr', 'shape'): - hkl_key = "%s_matrix_%s" % (mat_type, attrib) - if not six.PY2: - hkl_key = hkl_key.encode('ascii') - exclude_register.append(hkl_key) diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/lookup.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/lookup.py deleted file mode 100755 index 99d13df9..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/hickle/lookup.py +++ /dev/null @@ -1,238 +0,0 @@ -""" -#lookup.py - -This file contains all the mappings between hickle/HDF5 metadata and python types. -There are four dictionaries and one set that are populated here: - -1) types_dict -types_dict: mapping between python types and dataset creation functions, e.g. - types_dict = { - list: create_listlike_dataset, - int: create_python_dtype_dataset, - np.ndarray: create_np_array_dataset - } - -2) hkl_types_dict -hkl_types_dict: mapping between hickle metadata and dataset loading functions, e.g. - hkl_types_dict = { - "<type 'list'>" : load_list_dataset, - "<type 'tuple'>" : load_tuple_dataset - } - -3) container_types_dict -container_types_dict: mapping required to convert the PyContainer object in hickle.py - back into the required native type. PyContainer is required as - some iterable types are immutable (do not have an append() function). - Here is an example: - container_types_dict = { - "<type 'list'>": list, - "<type 'tuple'>": tuple - } - -4) container_key_types_dict -container_key_types_dict: mapping specifically for converting hickled dict data back into - a dictionary with the same key type. While python dictionary keys - can be any hashable object, in HDF5 a unicode/string is required - for a dataset name. Example: - container_key_types_dict = { - "<type 'str'>": str, - "<type 'unicode'>": unicode - } - -5) types_not_to_sort -type_not_to_sort is a list of hickle type attributes that may be hierarchical, -but don't require sorting by integer index. - -## Extending hickle to add support for other classes and types - -The process to add new load/dump capabilities is as follows: - -1) Create a file called load_[newstuff].py in loaders/ -2) In the load_[newstuff].py file, define your create_dataset and load_dataset functions, - along with all required mapping dictionaries. -3) Add an import call here, and populate the lookup dictionaries with update() calls: - # Add loaders for [newstuff] - try: - from .loaders.load_[newstuff[ import types_dict as ns_types_dict - from .loaders.load_[newstuff[ import hkl_types_dict as ns_hkl_types_dict - types_dict.update(ns_types_dict) - hkl_types_dict.update(ns_hkl_types_dict) - ... (Add container_types_dict etc if required) - except ImportError: - raise -""" - -import six -from ast import literal_eval - -def return_first(x): - """ Return first element of a list """ - return x[0] - -def load_nothing(h_hode): - pass - -types_dict = {} - -hkl_types_dict = {} - -types_not_to_sort = [b'dict', b'csr_matrix', b'csc_matrix', b'bsr_matrix'] - -container_types_dict = { - b"<type 'list'>": list, - b"<type 'tuple'>": tuple, - b"<type 'set'>": set, - b"<class 'list'>": list, - b"<class 'tuple'>": tuple, - b"<class 'set'>": set, - b"csr_matrix": return_first, - b"csc_matrix": return_first, - b"bsr_matrix": return_first - } - -# Technically, any hashable object can be used, for now sticking with built-in types -container_key_types_dict = { - b"<type 'str'>": literal_eval, - b"<type 'float'>": float, - b"<type 'bool'>": bool, - b"<type 'int'>": int, - b"<type 'complex'>": complex, - b"<type 'tuple'>": literal_eval, - b"<class 'str'>": literal_eval, - b"<class 'float'>": float, - b"<class 'bool'>": bool, - b"<class 'int'>": int, - b"<class 'complex'>": complex, - b"<class 'tuple'>": literal_eval - } - -if six.PY2: - container_key_types_dict[b"<type 'unicode'>"] = literal_eval - container_key_types_dict[b"<type 'long'>"] = long - -# Add loaders for built-in python types -if six.PY2: - from .loaders.load_python import types_dict as py_types_dict - from .loaders.load_python import hkl_types_dict as py_hkl_types_dict -else: - from .loaders.load_python3 import types_dict as py_types_dict - from .loaders.load_python3 import hkl_types_dict as py_hkl_types_dict - -types_dict.update(py_types_dict) -hkl_types_dict.update(py_hkl_types_dict) - -# Add loaders for numpy types -from .loaders.load_numpy import types_dict as np_types_dict -from .loaders.load_numpy import hkl_types_dict as np_hkl_types_dict -from .loaders.load_numpy import check_is_numpy_array -types_dict.update(np_types_dict) -hkl_types_dict.update(np_hkl_types_dict) - -####################### -## ND-ARRAY checking ## -####################### - -ndarray_like_check_fns = [ - check_is_numpy_array -] - -def check_is_ndarray_like(py_obj): - is_ndarray_like = False - for ii, check_fn in enumerate(ndarray_like_check_fns): - is_ndarray_like = check_fn(py_obj) - if is_ndarray_like: - break - return is_ndarray_like - - - - -####################### -## loading optional ## -####################### - -def register_class(myclass_type, hkl_str, dump_function, load_function, - to_sort=True, ndarray_check_fn=None): - """ Register a new hickle class. - - Args: - myclass_type type(class): type of class - dump_function (function def): function to write data to HDF5 - load_function (function def): function to load data from HDF5 - is_iterable (bool): Is the item iterable? - hkl_str (str): String to write to HDF5 file to describe class - to_sort (bool): If the item is iterable, does it require sorting? - ndarray_check_fn (function def): function to use to check if - - """ - types_dict.update({myclass_type: dump_function}) - hkl_types_dict.update({hkl_str: load_function}) - if to_sort == False: - types_not_to_sort.append(hkl_str) - if ndarray_check_fn is not None: - ndarray_like_check_fns.append(ndarray_check_fn) - -def register_class_list(class_list): - """ Register multiple classes in a list - - Args: - class_list (list): A list, where each item is an argument to - the register_class() function. - - Notes: This just runs the code: - for item in mylist: - register_class(*item) - """ - for class_item in class_list: - register_class(*class_item) - -def register_class_exclude(hkl_str_to_ignore): - """ Tell loading funciton to ignore any HDF5 dataset with attribute 'type=XYZ' - - Args: - hkl_str_to_ignore (str): attribute type=string to ignore and exclude from loading. - """ - hkl_types_dict[hkl_str_to_ignore] = load_nothing - -def register_exclude_list(exclude_list): - """ Ignore HDF5 datasets with attribute type='XYZ' from loading - - ArgsL - exclude_list (list): List of strings, which correspond to hdf5/hickle - type= attributes not to load. - """ - for hkl_str in exclude_list: - register_class_exclude(hkl_str) - -######################## -## Scipy sparse array ## -######################## - -try: - from .loaders.load_scipy import class_register, exclude_register - register_class_list(class_register) - register_exclude_list(exclude_register) -except ImportError: - pass -except NameError: - pass - -#################### -## Astropy stuff ## -#################### - -try: - from .loaders.load_astropy import class_register - register_class_list(class_register) -except ImportError: - pass - -################## -## Pandas stuff ## -################## - -try: - from .loaders.load_pandas import class_register - register_class_list(class_register) -except ImportError: - pass diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__init__.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/__init__.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/__init__.cpython-36.pyc deleted file mode 100755 index 86d97d222a8780ca54c672085ff548dfa6a28be0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmXr!<>hkDTM@&+z`*brM8Gg30|SEt0|P@b3j+f~3PUi1CZpd<h9ZzKg7{UZU!b3n zpPQ<mRa%@{RIHy-T3no)n3rd$pH*6vnw+Sgo1<HtT9#UrnWvwTnVg-I8lRb0T#}fR zqo0$Rq+d{3l98WhtY@ZQoLQ2pTacKXotU0l3{|RYtY@NUtXoiNtY@Z|nx3v-l3H9+ gtREkrnU`4-AFo$Xd5gm)H$SB`C)Ez*u40he0o-RgO8@`> diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_astropy.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_astropy.cpython-36.pyc deleted file mode 100755 index 8c672a706793402cf52bedb977e67f6a6b91ef51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3798 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 diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_hickle.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_hickle.cpython-36.pyc deleted file mode 100755 index 046d30d0527994b989f6c055be5a3cb573b6163f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18861 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 diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_hickle_helpers.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_hickle_helpers.cpython-36.pyc deleted file mode 100755 index d10d047823c6177abba7330f72046787d86a5e46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1969 zcmXr!<>hkDTM=`Eje+4Y0}|k7U|?`yU|=Xd!N9<f!Vtxf!kEI8!x+U>DFbFPM=_@` zrZDF)=dwhxFfydDM6rf5<VmnFq_Smm6*(|6fM5!16l)|y9#aHJH(L&SE=LqcE@u>H zE>{#6BS?%rhdY-iiieRQm9?lSg)xOAhc}lmijR>Yg)@b#g&~SRg*%0(g&|5Hg*Sz- zg&|5Xg+E20g&|5PMKDFEg&|5fRU}0?o2lqXsz5UXBSR`bm=pq&f?$%h=t!zCh?T+= z%%CY!<;SJ0P?B0)5}%QooSl;zpOKnVkXlr%S5V2t6`Ge>0+uXRNXsu$fT&Q&%}*)K zNmbC*Re-2fNGr`tF3HT#E7s%UdI<_LKTXD4Y{dnMMa8KhZko)u1d}sTle6P9i{mpA zi!&0Fa#E3mGD}j6z(NvGRZxC>W=U#pd`V?NswU$t5vW{od|qj8L1lbmQBh*0CgUw> zxOj1LW<g~<#8QZKGRP?~%)-FH;0%gBEd~aL5>QYxr7)*6H#4TNWOEdYl`u9jf<&7c zQ&_V(iq$~;6oz01O*X%mj0_A6FPT6DGXn!dh?^!;5y-S#e2&G%sYM`<yA~DY7p-I{ z;$dKb5WhP03-mMcb5r%RN{dsAiuE%}i;Hs;^YRS!vr3CnlN0rGb99SS%TkLn^YkIX z8lRb0T#}fRqo0$Rq+d{3l98WhtY@ZQoLQ2pTacKXotU0l3{|RYtY@NUtXoiNtY@Z| znx3u?ioaqoi5ZKx#6Ys~@Nj|!w-hKaK>lE06k{ynV_;ywA70IjDNNZM#R8y^0fkfw za|#PM{LsUzhyxT#MVz3p;9_840EHJQ;EF&w2oXdO7B2$>1G)=gX+$33LIK7iew;3J zLyOT8MsSQWfnv0TF@>?2v4j~!rZYif+o%LAm(Bp?JAwG%*k<(uyB^u`EJds!H!^4D zm4JP4i#07LKd}Vje0YQxfjuIN9Ml-eSOw%CHc*0O6l0WOED}QZ5y&EN8Vv&bsDv?# z2~@N|(kaxfG9}Cqe`T>?k+p)zf^>m>3yK>*kQmr^Z0NoVanoci0=eiGQ(nO>R&b^Q zdoqeCHxa83C6RrIk{Lnysu*Mz1EUP19Al9vvhP6g55i#Im4SVi1@>J!V>4qdLkU9` zV-|A?Bbdhs=CMF|OeL%}pm+kMJ*yJ7CdLxh8b)YZ^n&t1@d}cUg78b&vp7<iL1sb2 ztOz6y4gprbB2aD)0mrhNCg&|yaIsMY%H2_1$;CzSxrrr3nH3;*GMt?R7cXK5rD||O z76!3I7#J8dnWI=s;**PuAXGAlN-8cw3O;b!0GFePYzVd&rMNNxB@a+OWMJe2Ljgt* zED{GLKaTkL+{Dbh_;^jxTkP@iDf!9q@wZsPWnmH6C1N1wK)eAeWaGi+-{SVnEyyn_ z0hdove2{`h4^nCu7l9%KT#|uPc$6emIwwCd1ylimXh>-bP9oUl!PY=R1>|&aE(IrS zaQwsFo|l-L8Xu1oB;bq#4i^raTyTA22P!s-^%xi!SeQ5%nHV`3c^Eku`53vFM3{IO ZSr~a(I9NGYIoLSZI5;^N*`Sbx5di#C)lvWe diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_legacy_load.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_legacy_load.cpython-36.pyc deleted file mode 100755 index 387c9076b34bdbd560ab83a5798a241b2adc1ece..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmXr!<>hkDTM@&=%)s!N0SPcMFfceUFfbH5F)%QsFr+Z%FhoIU#wbQGpDBtNOtVC> zfN9n!))b}`<`#x1wp8{MmTaaXyHvJj21bSy#$X0b)|Vi|{gOc>2(vOUFbFa*FgSzk z*uucTP{NSKShS*qsf0O;Ifb#Av6-=!p@b!iHHE2}k&&TdLJflpLu_3wW2IOLTMZ*f ztb{#_1H`Ij3TG%(VPpWo63#3xkXXN4EmH|w4O13(7Edz+ST%?TWmhQGFoDEf7-Gd@ zm};48SxVSySP*Ip%fcC&7{VD+7y=oB7$O)V846V*7z$Ow8S*$v*ix85=A|$MGib8- zRSD*#rY9y>#%E;b6zgm0Wn|~vVoS^^PpmAi((nOGDdglQrex-&E9B?pR4SC`7iAYK zWacRZR2u0i1m_nORqAQ--eNA!thmJ-5NULatvJ7^BsJw0OL|Uz(k+hi#G<^+y!7H* zJjI#01v#l{nK>n?MYmWBiZb&`ZZU)GV*y!kizUOfpfZZZEi)(e7HeWjNm21F*36RB z++t1ETO4VbIjK3B#U&6{USe+QEyl!K%-N}xw^%@mRx%WcFfcIuYSS;!&&bbB)z2y| zPAw|d&nPV}&P~kAGt|#2ElN#J)X&Y)Elw><Ey~Q(&&W*9&Pk2W%quQQ%*oNu$xPBO zs4U6I&okCD(=W~}N!2Y#OwLYBPc4Qj)iu^L(KFU9s5I6y(@RZH*DpyeE-40+@z78N z`9!av@|FNd3R#dHlui^tDTk4bk&l^+iHnhmk%N(sk&Tguk&lswQHW89QG$tsu}F-8 zf#DWMe0*+VW?p=}CPxt)0|P@5NdGN1h?9%BKq5RKf*C}>bbx{-J{}wpNQ5ZZJe%D7 Zl+v73J4TQ@_!t-%I2fUji9?Ko5dg#O+^7Hm diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_scipy.cpython-36.pyc b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/__pycache__/test_scipy.cpython-36.pyc deleted file mode 100755 index 6f7dbb8741560fc88a3fb0bd2356c226bae2cd69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1718 zcmXr!<>hkDTM<*r#=!8H0SPcMFfceUFfbGsFfcHrFr+Z%Fhnt?Fr+Z$Fy%5wG3T;G zvE;Hwu`)vB*rM1{7*d#X*mF6eIKW~oIh?s%QCy4+sa#py%?w#Q%?ykTDXb}MEeuh- zDeNg6Eeuh7sr)IN*-S+_seB;WR9+C7!Whh;$@LQC6hBSoTU^P-Me(_bB}JJPAa*jG zodg%xWV|JvoRONG9iLeoU!0s-P#IrbkXTfl8lPBHlvt_Bc#AbBKRGcc8Du61gZ#$A zz`)=P@}Cg{149Wz3R?+d7E=myFH<c;33Cd2Gh;1d2}=z_Gh?w*32PIG&DhLXtOsJJ zFa$Gba`?SuW?*1=2{H#{LrO_yLF!9JkPygtO{OAt1_p*A4h9AWO{O9)5StssW-9_o z-(t!uxW$s0S7K2FGNp)>fq~%`pJQ=xYEemMex7SlQGSso(=F!WTmukcxRRkrkb!~W zSA%|menx(7s(w~!acWVqenx3=ac*K>o}qqLX;Er&qJD0UZgFZ^YEfpMenw_;c1~)1 zW?pegVor{JPG*vRL1jrsex9+OnSOC*Nvdu^Vsdt3dTKFLsjjh}iJq};L8Y;tnO<so zx_(J&aY-?lgaoTzLFFwzkRUjq!9mOm3PO-485sE(Ihc4Di-Z{%7~mnz!@$4*3I}jV zpJD`uG%qZqvzVJ1Y8grxvsh9<kTr!31k>5TVGj`niLiiD4Oo;3tQMq>F@*_~hQOlC zB@8vpHH<Y(X-sKMDSRoMy-c+%C9Ftd{9rLwux^$VwiLz`j&zo0##&IEgKS2%g&nL8 z&6X^-6sBgzEcO%*kQ<wsYne+pYM5)-YuM75Qv|@~bChsqan-P-a5XbAGL&#;ai?%K zGuCo~MOjn0;iBBljI~@~QH~TIxF}CEV=Z?HPYq`YLo?F^P)g%%Vl3gQ;VNMT^X*C? zeC`qsFy9Z%XUyWO;mqQ%VaehLi>AOuxw80cSfQd-a8d3o{u&Ob=md~x4QG}>4NI0l zHptFJU=gk?ff`n*$QG~&ca}g62UO%3NCcb%1pSbbIAakfD2ap8KO(We1SRX2Y@lS% zc#E|-Be5X0iVK{6iVO5IOslw|Y$Ifjv0jELTJ8a*Ah2C9agcx}Q;{ghN)Vwb2+mbS zpyXBrN|I6RCHdgYe~T4Nfpgg{wxZO6)Wnh~_M%j<V~RkT_ZAx@qugRiDa|do#gdbs zm~x9NvlyIj@{&`F_!t-%qBs(Ba*}iMi&Jm0q$HLk7Kwp8#Z$x&%D2o#`Q^8mlk;<m zWI+xR0I6p#&NYf+%gjqDC@H$do|%`DnVec2#ax_g9K~9kYZ#vaqKqJvaeM|icS8sv zkdZ>rkO7xskkSw2&tfA`@x>^_B*qAWB8(zTLX2XJYK%fmJd9k7P|PI2D8MKHQNtv} zD8yK#2r`o+K0Y@wGcP_~Q{WbBUTJPYB{;mIc)&%b9;C>Ggd@020tHTyB*-(8kPy-X z1x;#EF_?yw2;hP%ioKvxuOP7`qX-n$Q9S9XCGjPxxdlb}`6ahllQU8>i@>D<+!=X^ zxvBB-5buJDH3$praSof@{FKt1R69^gDi&d2VBlaBVd7xqVd7!tVdmiAP~u=@V*~(3 CXrK@P diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_astropy.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_astropy.py deleted file mode 100755 index 2086ec37..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_astropy.py +++ /dev/null @@ -1,133 +0,0 @@ -import hickle as hkl -from astropy.units import Quantity -from astropy.time import Time -from astropy.coordinates import Angle, SkyCoord -from astropy.constants import Constant, EMConstant, G -from astropy.table import Table -import numpy as np -from py.path import local - -# Set the current working directory to the temporary directory -local.get_temproot().chdir() - -def test_astropy_quantity(): - - for uu in ['m^3', 'm^3 / s', 'kg/pc']: - a = Quantity(7, unit=uu) - - hkl.dump(a, "test_ap.h5") - b = hkl.load("test_ap.h5") - - assert a == b - assert a.unit == b.unit - - a *= a - hkl.dump(a, "test_ap.h5") - b = hkl.load("test_ap.h5") - assert a == b - assert a.unit == b.unit - -def TODO_test_astropy_constant(): - hkl.dump(G, "test_ap.h5") - gg = hkl.load("test_ap.h5") - - print(G) - print(gg) - -def test_astropy_table(): - t = Table([[1, 2], [3, 4]], names=('a', 'b'), meta={'name': 'test_thing'}) - - hkl.dump({'a': t}, "test_ap.h5") - t2 = hkl.load("test_ap.h5")['a'] - - print(t) - print(t.meta) - print(t2) - print(t2.meta) - - print(t.dtype, t2.dtype) - assert t.meta == t2.meta - assert t.dtype == t2.dtype - - assert np.allclose(t['a'].astype('float32'), t2['a'].astype('float32')) - assert np.allclose(t['b'].astype('float32'), t2['b'].astype('float32')) - -def test_astropy_quantity_array(): - a = Quantity([1,2,3], unit='m') - - hkl.dump(a, "test_ap.h5") - b = hkl.load("test_ap.h5") - - assert np.allclose(a.value, b.value) - assert a.unit == b.unit - -def test_astropy_time_array(): - times = ['1999-01-01T00:00:00.123456789', '2010-01-01T00:00:00'] - t1 = Time(times, format='isot', scale='utc') - hkl.dump(t1, "test_ap2.h5") - t2 = hkl.load("test_ap2.h5") - - print(t1) - print(t2) - assert t1.value.shape == t2.value.shape - for ii in range(len(t1)): - assert t1.value[ii] == t2.value[ii] - assert t1.format == t2.format - assert t1.scale == t2.scale - - times = [58264, 58265, 58266] - t1 = Time(times, format='mjd', scale='utc') - hkl.dump(t1, "test_ap2.h5") - t2 = hkl.load("test_ap2.h5") - - print(t1) - print(t2) - assert t1.value.shape == t2.value.shape - assert np.allclose(t1.value, t2.value) - assert t1.format == t2.format - assert t1.scale == t2.scale - -def test_astropy_angle(): - for uu in ['radian', 'degree']: - a = Angle(1.02, unit=uu) - - hkl.dump(a, "test_ap.h5") - b = hkl.load("test_ap.h5") - assert a == b - assert a.unit == b.unit - -def test_astropy_angle_array(): - a = Angle([1,2,3], unit='degree') - - hkl.dump(a, "test_ap.h5") - b = hkl.load("test_ap.h5") - - assert np.allclose(a.value, b.value) - assert a.unit == b.unit - -def test_astropy_skycoord(): - ra = Angle(['1d20m', '1d21m'], unit='degree') - dec = Angle(['33d0m0s', '33d01m'], unit='degree') - radec = SkyCoord(ra, dec) - hkl.dump(radec, "test_ap.h5") - radec2 = hkl.load("test_ap.h5") - assert np.allclose(radec.ra.value, radec2.ra.value) - assert np.allclose(radec.dec.value, radec2.dec.value) - - ra = Angle(['1d20m', '1d21m'], unit='hourangle') - dec = Angle(['33d0m0s', '33d01m'], unit='degree') - radec = SkyCoord(ra, dec) - hkl.dump(radec, "test_ap.h5") - radec2 = hkl.load("test_ap.h5") - assert np.allclose(radec.ra.value, radec2.ra.value) - assert np.allclose(radec.dec.value, radec2.dec.value) - -if __name__ == "__main__": - test_astropy_quantity() - #test_astropy_constant() - test_astropy_table() - test_astropy_quantity_array() - test_astropy_time_array() - test_astropy_angle() - test_astropy_angle_array() - test_astropy_skycoord() diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle.py deleted file mode 100755 index 54910542..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle.py +++ /dev/null @@ -1,826 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -""" -# test_hickle.py - -Unit tests for hickle module. - -""" - -import h5py -import hashlib -import numpy as np -import os -import six -import time -from pprint import pprint - -from py.path import local - -import hickle -from hickle.hickle import * - - -# Set current working directory to the temporary directory -local.get_temproot().chdir() - -NESTED_DICT = { - "level1_1": { - "level2_1": [1, 2, 3], - "level2_2": [4, 5, 6] - }, - "level1_2": { - "level2_1": [1, 2, 3], - "level2_2": [4, 5, 6] - }, - "level1_3": { - "level2_1": { - "level3_1": [1, 2, 3], - "level3_2": [4, 5, 6] - }, - "level2_2": [4, 5, 6] - } -} - -DUMP_CACHE = [] # Used in test_track_times() - - -def test_string(): - """ Dumping and loading a string """ - if six.PY2: - filename, mode = 'test.h5', 'w' - string_obj = "The quick brown fox jumps over the lazy dog" - dump(string_obj, filename, mode) - string_hkl = load(filename) - #print "Initial list: %s"%list_obj - #print "Unhickled data: %s"%list_hkl - assert type(string_obj) == type(string_hkl) == str - assert string_obj == string_hkl - else: - pass - - -def test_unicode(): - """ Dumping and loading a unicode string """ - if six.PY2: - filename, mode = 'test.h5', 'w' - u = unichr(233) + unichr(0x0bf2) + unichr(3972) + unichr(6000) - dump(u, filename, mode) - u_hkl = load(filename) - - assert type(u) == type(u_hkl) == unicode - assert u == u_hkl - # For those interested, uncomment below to see what those codes are: - # for i, c in enumerate(u_hkl): - # print i, '%04x' % ord(c), unicodedata.category(c), - # print unicodedata.name(c) - else: - pass - - -def test_unicode2(): - if six.PY2: - a = u"unicode test" - dump(a, 'test.hkl', mode='w') - - z = load('test.hkl') - assert a == z - assert type(a) == type(z) == unicode - pprint(z) - else: - pass - -def test_list(): - """ Dumping and loading a list """ - filename, mode = 'test_list.h5', 'w' - list_obj = [1, 2, 3, 4, 5] - dump(list_obj, filename, mode=mode) - list_hkl = load(filename) - #print(f'Initial list: {list_obj}') - #print(f'Unhickled data: {list_hkl}') - try: - assert type(list_obj) == type(list_hkl) == list - assert list_obj == list_hkl - import h5py - a = h5py.File(filename) - a.close() - - except AssertionError: - print("ERR:", list_obj, list_hkl) - import h5py - - raise() - - -def test_set(): - """ Dumping and loading a list """ - filename, mode = 'test_set.h5', 'w' - list_obj = set([1, 0, 3, 4.5, 11.2]) - dump(list_obj, filename, mode) - list_hkl = load(filename) - #print "Initial list: %s"%list_obj - #print "Unhickled data: %s"%list_hkl - try: - assert type(list_obj) == type(list_hkl) == set - assert list_obj == list_hkl - except AssertionError: - print(type(list_obj)) - print(type(list_hkl)) - #os.remove(filename) - raise - - -def test_numpy(): - """ Dumping and loading numpy array """ - filename, mode = 'test.h5', 'w' - dtypes = ['float32', 'float64', 'complex64', 'complex128'] - - for dt in dtypes: - array_obj = np.ones(8, dtype=dt) - dump(array_obj, filename, mode) - array_hkl = load(filename) - try: - assert array_hkl.dtype == array_obj.dtype - assert np.all((array_hkl, array_obj)) - except AssertionError: - print(array_hkl) - print(array_obj) - raise - - -def test_masked(): - """ Test masked numpy array """ - filename, mode = 'test.h5', 'w' - a = np.ma.array([1,2,3,4], dtype='float32', mask=[0,1,0,0]) - - dump(a, filename, mode) - a_hkl = load(filename) - - try: - assert a_hkl.dtype == a.dtype - assert np.all((a_hkl, a)) - except AssertionError: - print(a_hkl) - print(a) - raise - - -def test_dict(): - """ Test dictionary dumping and loading """ - filename, mode = 'test.h5', 'w' - - dd = { - 'name' : b'Danny', - 'age' : 28, - 'height' : 6.1, - 'dork' : True, - 'nums' : [1, 2, 3], - 'narr' : np.array([1,2,3]), - #'unic' : u'dan[at]thetelegraphic.com' - } - - - dump(dd, filename, mode) - dd_hkl = load(filename) - - for k in dd.keys(): - try: - assert k in dd_hkl.keys() - - if type(dd[k]) is type(np.array([1])): - assert np.all((dd[k], dd_hkl[k])) - else: - #assert dd_hkl[k] == dd[k] - pass - assert type(dd_hkl[k]) == type(dd[k]) - except AssertionError: - print(k) - print(dd_hkl[k]) - print(dd[k]) - print(type(dd_hkl[k]), type(dd[k])) - raise - - -def test_empty_dict(): - """ Test empty dictionary dumping and loading """ - filename, mode = 'test.h5', 'w' - - dump({}, filename, mode) - assert load(filename) == {} - - -def test_compression(): - """ Test compression on datasets""" - - filename, mode = 'test.h5', 'w' - dtypes = ['int32', 'float32', 'float64', 'complex64', 'complex128'] - - comps = [None, 'gzip', 'lzf'] - - for dt in dtypes: - for cc in comps: - array_obj = np.ones(32768, dtype=dt) - dump(array_obj, filename, mode, compression=cc) - print(cc, os.path.getsize(filename)) - array_hkl = load(filename) - try: - assert array_hkl.dtype == array_obj.dtype - assert np.all((array_hkl, array_obj)) - except AssertionError: - print(array_hkl) - print(array_obj) - raise - - -def test_dict_int_key(): - """ Test for dictionaries with integer keys """ - filename, mode = 'test.h5', 'w' - - dd = { - 0: "test", - 1: "test2" - } - - dump(dd, filename, mode) - dd_hkl = load(filename) - - -def test_dict_nested(): - """ Test for dictionaries with integer keys """ - filename, mode = 'test.h5', 'w' - - dd = NESTED_DICT - - dump(dd, filename, mode) - dd_hkl = load(filename) - - ll_hkl = dd_hkl["level1_3"]["level2_1"]["level3_1"] - ll = dd["level1_3"]["level2_1"]["level3_1"] - assert ll == ll_hkl - - -def test_masked_dict(): - """ Test dictionaries with masked arrays """ - - filename, mode = 'test.h5', 'w' - - dd = { - "data" : np.ma.array([1,2,3], mask=[True, False, False]), - "data2" : np.array([1,2,3,4,5]) - } - - dump(dd, filename, mode) - dd_hkl = load(filename) - - for k in dd.keys(): - try: - assert k in dd_hkl.keys() - if type(dd[k]) is type(np.array([1])): - assert np.all((dd[k], dd_hkl[k])) - elif type(dd[k]) is type(np.ma.array([1])): - print(dd[k].data) - print(dd_hkl[k].data) - assert np.allclose(dd[k].data, dd_hkl[k].data) - assert np.allclose(dd[k].mask, dd_hkl[k].mask) - - assert type(dd_hkl[k]) == type(dd[k]) - - except AssertionError: - print(k) - print(dd_hkl[k]) - print(dd[k]) - print(type(dd_hkl[k]), type(dd[k])) - raise - - -def test_np_float(): - """ Test for singular np dtypes """ - filename, mode = 'np_float.h5', 'w' - - dtype_list = (np.float16, np.float32, np.float64, - np.complex64, np.complex128, - np.int8, np.int16, np.int32, np.int64, - np.uint8, np.uint16, np.uint32, np.uint64) - - for dt in dtype_list: - - dd = dt(1) - dump(dd, filename, mode) - dd_hkl = load(filename) - assert dd == dd_hkl - assert dd.dtype == dd_hkl.dtype - - dd = {} - for dt in dtype_list: - dd[str(dt)] = dt(1.0) - dump(dd, filename, mode) - dd_hkl = load(filename) - - print(dd) - for dt in dtype_list: - assert dd[str(dt)] == dd_hkl[str(dt)] - - -def md5sum(filename, blocksize=65536): - """ Compute MD5 sum for a given file """ - hash = hashlib.md5() - - with open(filename, "r+b") as f: - for block in iter(lambda: f.read(blocksize), ""): - hash.update(block) - return hash.hexdigest() - - -def caching_dump(obj, filename, *args, **kwargs): - """ Save arguments of all dump calls """ - DUMP_CACHE.append((obj, filename, args, kwargs)) - return hickle_dump(obj, filename, *args, **kwargs) - - -def test_track_times(): - """ Verify that track_times = False produces identical files """ - hashes = [] - for obj, filename, mode, kwargs in DUMP_CACHE: - if isinstance(filename, hickle.H5FileWrapper): - filename = str(filename.file_name) - kwargs['track_times'] = False - caching_dump(obj, filename, mode, **kwargs) - hashes.append(md5sum(filename)) - - time.sleep(1) - - for hash1, (obj, filename, mode, kwargs) in zip(hashes, DUMP_CACHE): - if isinstance(filename, hickle.H5FileWrapper): - filename = str(filename.file_name) - caching_dump(obj, filename, mode, **kwargs) - hash2 = md5sum(filename) - print(hash1, hash2) - assert hash1 == hash2 - - -def test_comp_kwargs(): - """ Test compression with some kwargs for shuffle and chunking """ - - filename, mode = 'test.h5', 'w' - dtypes = ['int32', 'float32', 'float64', 'complex64', 'complex128'] - - comps = [None, 'gzip', 'lzf'] - chunks = [(100, 100), (250, 250)] - shuffles = [True, False] - scaleoffsets = [0, 1, 2] - - for dt in dtypes: - for cc in comps: - for ch in chunks: - for sh in shuffles: - for so in scaleoffsets: - kwargs = { - 'compression' : cc, - 'dtype': dt, - 'chunks': ch, - 'shuffle': sh, - 'scaleoffset': so - } - #array_obj = np.random.random_integers(low=-8192, high=8192, size=(1000, 1000)).astype(dt) - array_obj = NESTED_DICT - dump(array_obj, filename, mode, compression=cc) - print(kwargs, os.path.getsize(filename)) - array_hkl = load(filename) - - -def test_list_numpy(): - """ Test converting a list of numpy arrays """ - - filename, mode = 'test.h5', 'w' - - a = np.ones(1024) - b = np.zeros(1000) - c = [a, b] - - dump(c, filename, mode) - dd_hkl = load(filename) - - print(dd_hkl) - - assert isinstance(dd_hkl, list) - assert isinstance(dd_hkl[0], np.ndarray) - - -def test_tuple_numpy(): - """ Test converting a list of numpy arrays """ - - filename, mode = 'test.h5', 'w' - - a = np.ones(1024) - b = np.zeros(1000) - c = (a, b, a) - - dump(c, filename, mode) - dd_hkl = load(filename) - - print(dd_hkl) - - assert isinstance(dd_hkl, tuple) - assert isinstance(dd_hkl[0], np.ndarray) - - -def test_none(): - """ Test None type hickling """ - - filename, mode = 'test.h5', 'w' - - a = None - - dump(a, filename, mode) - dd_hkl = load(filename) - print(a) - print(dd_hkl) - - assert isinstance(dd_hkl, type(None)) - - -def test_dict_none(): - """ Test None type hickling """ - - filename, mode = 'test.h5', 'w' - - a = {'a': 1, 'b' : None} - - dump(a, filename, mode) - dd_hkl = load(filename) - print(a) - print(dd_hkl) - - assert isinstance(a['b'], type(None)) - - -def test_file_open_close(): - """ https://github.com/telegraphic/hickle/issues/20 """ - import h5py - f = h5py.File('test.hdf', 'w') - a = np.arange(5) - - dump(a, 'test.hkl') - dump(a, 'test.hkl') - - dump(a, f, mode='w') - f.close() - try: - dump(a, f, mode='w') - except hickle.hickle.ClosedFileError: - print("Tests: Closed file exception caught") - - -def test_list_order(): - """ https://github.com/telegraphic/hickle/issues/26 """ - d = [np.arange(n + 1) for n in range(20)] - hickle.dump(d, 'test.h5') - d_hkl = hickle.load('test.h5') - - try: - for ii, xx in enumerate(d): - assert d[ii].shape == d_hkl[ii].shape - for ii, xx in enumerate(d): - assert np.allclose(d[ii], d_hkl[ii]) - except AssertionError: - print(d[ii], d_hkl[ii]) - raise - - -def test_embedded_array(): - """ See https://github.com/telegraphic/hickle/issues/24 """ - - d_orig = [[np.array([10., 20.]), np.array([10, 20, 30])], [np.array([10, 2]), np.array([1.])]] - hickle.dump(d_orig, 'test.h5') - d_hkl = hickle.load('test.h5') - - for ii, xx in enumerate(d_orig): - for jj, yy in enumerate(xx): - assert np.allclose(d_orig[ii][jj], d_hkl[ii][jj]) - - print(d_hkl) - print(d_orig) - - -################ -## NEW TESTS ## -################ - - -def generate_nested(): - a = [1, 2, 3] - b = [a, a, a] - c = [a, b, 's'] - d = [a, b, c, c, a] - e = [d, d, d, d, 1] - f = {'a' : a, 'b' : b, 'e' : e} - g = {'f' : f, 'a' : e, 'd': d} - h = {'h': g, 'g' : f} - z = [f, a, b, c, d, e, f, g, h, g, h] - a = np.array([1, 2, 3, 4]) - b = set([1, 2, 3, 4, 5]) - c = (1, 2, 3, 4, 5) - d = np.ma.array([1, 2, 3, 4, 5, 6, 7, 8]) - z = {'a': a, 'b': b, 'c': c, 'd': d, 'z': z} - return z - - -def test_is_iterable(): - a = [1, 2, 3] - b = 1 - - assert check_is_iterable(a) == True - assert check_is_iterable(b) == False - - -def test_check_iterable_item_type(): - - a = [1, 2, 3] - b = [a, a, a] - c = [a, b, 's'] - - type_a = check_iterable_item_type(a) - type_b = check_iterable_item_type(b) - type_c = check_iterable_item_type(c) - - assert type_a is int - assert type_b is list - assert type_c == False - - -def test_dump_nested(): - """ Dump a complicated nested object to HDF5 - """ - z = generate_nested() - dump(z, 'test.hkl', mode='w') - - -def test_with_dump(): - lst = [1] - tpl = (1) - dct = {1: 1} - arr = np.array([1]) - - with h5py.File('test.hkl') as file: - dump(lst, file, path='/lst') - dump(tpl, file, path='/tpl') - dump(dct, file, path='/dct') - dump(arr, file, path='/arr') - - -def test_with_load(): - lst = [1] - tpl = (1) - dct = {1: 1} - arr = np.array([1]) - - with h5py.File('test.hkl') as file: - assert load(file, '/lst') == lst - assert load(file, '/tpl') == tpl - assert load(file, '/dct') == dct - assert load(file, '/arr') == arr - - -def test_load(): - - a = set([1, 2, 3, 4]) - b = set([5, 6, 7, 8]) - c = set([9, 10, 11, 12]) - z = (a, b, c) - z = [z, z] - z = (z, z, z, z, z) - - print("Original:") - pprint(z) - dump(z, 'test.hkl', mode='w') - - print("\nReconstructed:") - z = load('test.hkl') - pprint(z) - - -def test_sort_keys(): - keys = [b'data_0', b'data_1', b'data_2', b'data_3', b'data_10'] - keys_sorted = [b'data_0', b'data_1', b'data_2', b'data_3', b'data_10'] - - print(keys) - print(keys_sorted) - assert sort_keys(keys) == keys_sorted - - -def test_ndarray(): - - a = np.array([1,2,3]) - b = np.array([2,3,4]) - z = (a, b) - - print("Original:") - pprint(z) - dump(z, 'test.hkl', mode='w') - - print("\nReconstructed:") - z = load('test.hkl') - pprint(z) - - -def test_ndarray_masked(): - - a = np.ma.array([1,2,3]) - b = np.ma.array([2,3,4], mask=[True, False, True]) - z = (a, b) - - print("Original:") - pprint(z) - dump(z, 'test.hkl', mode='w') - - print("\nReconstructed:") - z = load('test.hkl') - pprint(z) - - -def test_simple_dict(): - a = {'key1': 1, 'key2': 2} - - dump(a, 'test.hkl') - z = load('test.hkl') - - pprint(a) - pprint(z) - - -def test_complex_dict(): - a = {'akey': 1, 'akey2': 2} - if six.PY2: - # NO LONG TYPE IN PY3! - b = {'bkey': 2.0, 'bkey3': long(3.0)} - else: - b = a - c = {'ckey': "hello", "ckey2": "hi there"} - z = {'zkey1': a, 'zkey2': b, 'zkey3': c} - - print("Original:") - pprint(z) - dump(z, 'test.hkl', mode='w') - - print("\nReconstructed:") - z = load('test.hkl') - pprint(z) - -def test_multi_hickle(): - a = {'a': 123, 'b': [1, 2, 4]} - - if os.path.exists("test.hkl"): - os.remove("test.hkl") - dump(a, "test.hkl", path="/test", mode="w") - dump(a, "test.hkl", path="/test2", mode="r+") - dump(a, "test.hkl", path="/test3", mode="r+") - dump(a, "test.hkl", path="/test4", mode="r+") - - a = load("test.hkl", path="/test") - b = load("test.hkl", path="/test2") - c = load("test.hkl", path="/test3") - d = load("test.hkl", path="/test4") - -def test_complex(): - """ Test complex value dtype is handled correctly - - https://github.com/telegraphic/hickle/issues/29 """ - - data = {"A":1.5, "B":1.5 + 1j, "C":np.linspace(0,1,4) + 2j} - dump(data, "test.hkl") - data2 = load("test.hkl") - for key in data.keys(): - assert type(data[key]) == type(data2[key]) - -def test_nonstring_keys(): - """ Test that keys are reconstructed back to their original datatypes - https://github.com/telegraphic/hickle/issues/36 - """ - if six.PY2: - u = unichr(233) + unichr(0x0bf2) + unichr(3972) + unichr(6000) - - data = {u'test': 123, - 'def': 456, - 'hik' : np.array([1,2,3]), - u: u, - 0: 0, - True: 'hi', - 1.1 : 'hey', - #2L : 'omg', - 1j: 'complex_hashable', - (1, 2): 'boo', - ('A', 17.4, 42): [1, 7, 'A'], - (): '1313e was here', - '0': 0 - } - #data = {'0': 123, 'def': 456} - print(data) - dump(data, "test.hkl") - data2 = load("test.hkl") - print(data2) - - for key in data.keys(): - assert key in data2.keys() - - print(data2) - else: - pass - -def test_scalar_compression(): - """ Test bug where compression causes a crash on scalar datasets - - (Scalars are incompressible!) - https://github.com/telegraphic/hickle/issues/37 - """ - data = {'a' : 0, 'b' : np.float(2), 'c' : True} - - dump(data, "test.hkl", compression='gzip') - data2 = load("test.hkl") - - print(data2) - for key in data.keys(): - assert type(data[key]) == type(data2[key]) - -def test_bytes(): - """ Dumping and loading a string. PYTHON3 ONLY """ - if six.PY3: - filename, mode = 'test.h5', 'w' - string_obj = b"The quick brown fox jumps over the lazy dog" - dump(string_obj, filename, mode) - string_hkl = load(filename) - #print "Initial list: %s"%list_obj - #print "Unhickled data: %s"%list_hkl - print(type(string_obj)) - print(type(string_hkl)) - assert type(string_obj) == type(string_hkl) == bytes - assert string_obj == string_hkl - else: - pass - -def test_np_scalar(): - """ Numpy scalar datatype - - https://github.com/telegraphic/hickle/issues/50 - """ - - fid='test.h5py' - r0={'test': np.float64(10.)} - s = dump(r0, fid) - r = load(fid) - print(r) - assert type(r0['test']) == type(r['test']) - -if __name__ == '__main__': - """ Some tests and examples """ - test_sort_keys() - - test_np_scalar() - test_scalar_compression() - test_complex() - test_file_open_close() - test_dict_none() - test_none() - test_masked_dict() - test_list() - test_set() - test_numpy() - test_dict() - test_empty_dict() - test_compression() - test_masked() - test_dict_nested() - test_comp_kwargs() - test_list_numpy() - test_tuple_numpy() - test_track_times() - test_list_order() - test_embedded_array() - test_np_float() - - if six.PY2: - test_unicode() - test_unicode2() - test_string() - test_nonstring_keys() - - if six.PY3: - test_bytes() - - - # NEW TESTS - test_is_iterable() - test_check_iterable_item_type() - test_dump_nested() - test_with_dump() - test_with_load() - test_load() - test_sort_keys() - test_ndarray() - test_ndarray_masked() - test_simple_dict() - test_complex_dict() - test_multi_hickle() - test_dict_int_key() - - # Cleanup - print("ALL TESTS PASSED!") \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle_helpers.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle_helpers.py deleted file mode 100755 index 253839e9..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_hickle_helpers.py +++ /dev/null @@ -1,63 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -""" -# test_hickle_helpers.py - -Unit tests for hickle module -- helper functions. - -""" - -import numpy as np -try: - import scipy - from scipy import sparse - _has_scipy = True -except ImportError: - _has_scipy = False - -from hickle.helpers import check_is_hashable, check_is_iterable, check_iterable_item_type - -from hickle.loaders.load_numpy import check_is_numpy_array -if _has_scipy: - from hickle.loaders.load_scipy import check_is_scipy_sparse_array - - - -def test_check_is_iterable(): - assert check_is_iterable([1,2,3]) is True - assert check_is_iterable(1) is False - - -def test_check_is_hashable(): - assert check_is_hashable(1) is True - assert check_is_hashable([1,2,3]) is False - - -def test_check_iterable_item_type(): - assert check_iterable_item_type([1,2,3]) is int - assert check_iterable_item_type([int(1), float(1)]) is False - assert check_iterable_item_type([]) is False - - -def test_check_is_numpy_array(): - assert check_is_numpy_array(np.array([1,2,3])) is True - assert check_is_numpy_array(np.ma.array([1,2,3])) is True - assert check_is_numpy_array([1,2]) is False - - -def test_check_is_scipy_sparse_array(): - t_csr = scipy.sparse.csr_matrix([0]) - t_csc = scipy.sparse.csc_matrix([0]) - t_bsr = scipy.sparse.bsr_matrix([0]) - assert check_is_scipy_sparse_array(t_csr) is True - assert check_is_scipy_sparse_array(t_csc) is True - assert check_is_scipy_sparse_array(t_bsr) is True - assert check_is_scipy_sparse_array(np.array([1])) is False - -if __name__ == "__main__": - test_check_is_hashable() - test_check_is_iterable() - test_check_is_numpy_array() - test_check_iterable_item_type() - if _has_scipy: - test_check_is_scipy_sparse_array() \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_legacy_load.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_legacy_load.py deleted file mode 100755 index e849bcf6..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_legacy_load.py +++ /dev/null @@ -1,30 +0,0 @@ -import glob -import warnings -import hickle as hkl -import h5py -import six - -def test_legacy_load(): - if six.PY2: - filelist = sorted(glob.glob('legacy_hkls/*.hkl')) - - # Make all warnings show - warnings.simplefilter("always") - - for filename in filelist: - try: - print(filename) - a = hkl.load(filename) - except: - with h5py.File(filename) as a: - print(a.attrs.items()) - print(a.items()) - for key, item in a.items(): - print(item.attrs.items()) - raise - else: - print("Legacy loading only works in Py2. Sorry.") - pass - -if __name__ == "__main__": - test_legacy_load() \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_scipy.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_scipy.py deleted file mode 100755 index ab78311d..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/hickle-3.4.3-py3.6.egg/tests/test_scipy.py +++ /dev/null @@ -1,57 +0,0 @@ -import numpy as np -from scipy.sparse import csr_matrix, csc_matrix, bsr_matrix - -import hickle -from hickle.loaders.load_scipy import check_is_scipy_sparse_array - -from py.path import local - -# Set the current working directory to the temporary directory -local.get_temproot().chdir() - - -def test_is_sparse(): - sm0 = csr_matrix((3, 4), dtype=np.int8) - sm1 = csc_matrix((1, 2)) - - assert check_is_scipy_sparse_array(sm0) - assert check_is_scipy_sparse_array(sm1) - - -def test_sparse_matrix(): - sm0 = csr_matrix((3, 4), dtype=np.int8).toarray() - - row = np.array([0, 0, 1, 2, 2, 2]) - col = np.array([0, 2, 2, 0, 1, 2]) - data = np.array([1, 2, 3, 4, 5, 6]) - sm1 = csr_matrix((data, (row, col)), shape=(3, 3)) - sm2 = csc_matrix((data, (row, col)), shape=(3, 3)) - - indptr = np.array([0, 2, 3, 6]) - indices = np.array([0, 2, 2, 0, 1, 2]) - data = np.array([1, 2, 3, 4, 5, 6]).repeat(4).reshape(6, 2, 2) - sm3 = bsr_matrix((data,indices, indptr), shape=(6, 6)) - - hickle.dump(sm1, 'test_sp.h5') - sm1_h = hickle.load('test_sp.h5') - hickle.dump(sm2, 'test_sp2.h5') - sm2_h = hickle.load('test_sp2.h5') - hickle.dump(sm3, 'test_sp3.h5') - sm3_h = hickle.load('test_sp3.h5') - - assert isinstance(sm1_h, csr_matrix) - assert isinstance(sm2_h, csc_matrix) - assert isinstance(sm3_h, bsr_matrix) - - assert np.allclose(sm1_h.data, sm1.data) - assert np.allclose(sm2_h.data, sm2.data) - assert np.allclose(sm3_h.data, sm3.data) - - assert sm1_h. shape == sm1.shape - assert sm2_h. shape == sm2.shape - assert sm3_h. shape == sm3.shape - - -if __name__ == "__main__": - test_sparse_matrix() - test_is_sparse() \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/site.py b/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/site.py deleted file mode 100755 index 0d2d2ff8..00000000 --- a/workflow_parallel_frame_prediction/Training/hickle/lib/python3.6/site-packages/site.py +++ /dev/null @@ -1,74 +0,0 @@ -def __boot(): - import sys - import os - PYTHONPATH = os.environ.get('PYTHONPATH') - if PYTHONPATH is None or (sys.platform == 'win32' and not PYTHONPATH): - PYTHONPATH = [] - else: - PYTHONPATH = PYTHONPATH.split(os.pathsep) - - pic = getattr(sys, 'path_importer_cache', {}) - stdpath = sys.path[len(PYTHONPATH):] - mydir = os.path.dirname(__file__) - - for item in stdpath: - if item == mydir or not item: - continue # skip if current dir. on Windows, or my own directory - importer = pic.get(item) - if importer is not None: - loader = importer.find_module('site') - if loader is not None: - # This should actually reload the current module - loader.load_module('site') - break - else: - try: - import imp # Avoid import loop in Python >= 3.3 - stream, path, descr = imp.find_module('site', [item]) - except ImportError: - continue - if stream is None: - continue - try: - # This should actually reload the current module - imp.load_module('site', stream, path, descr) - finally: - stream.close() - break - else: - raise ImportError("Couldn't find the real 'site' module") - - known_paths = dict([(makepath(item)[1], 1) for item in sys.path]) # 2.2 comp - - oldpos = getattr(sys, '__egginsert', 0) # save old insertion position - sys.__egginsert = 0 # and reset the current one - - for item in PYTHONPATH: - addsitedir(item) - - sys.__egginsert += oldpos # restore effective old position - - d, nd = makepath(stdpath[0]) - insert_at = None - new_path = [] - - for item in sys.path: - p, np = makepath(item) - - if np == nd and insert_at is None: - # We've hit the first 'system' path entry, so added entries go here - insert_at = len(new_path) - - if np in known_paths or insert_at is None: - new_path.append(item) - else: - # new path after the insert point, back-insert it - new_path.insert(insert_at, item) - insert_at += 1 - - sys.path[:] = new_path - - -if __name__ == 'site': - __boot() - del __boot diff --git a/workflow_parallel_frame_prediction/Training/horovodJob.sh b/workflow_parallel_frame_prediction/Training/horovodJob.sh deleted file mode 100644 index 236a08d9..00000000 --- a/workflow_parallel_frame_prediction/Training/horovodJob.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -#SBATCH --account=deepacf -# budget account where contingent is taken from# TASKS = NODES * GPUS_PER_NODE -#SBATCH --nodes=3 -#SBATCH --ntasks-per-node=4 -#SBATCH --ntasks=12 -# can be omitted if --nodes and --ntasks-per-node -# are given -# SBATCH --cpus-per-task=1 -# for OpenMP/hybrid jobs only -#SBATCH --output=horovod-%j.out -# if keyword omitted: Default is slurm-%j.out in -# the submission directory (%j is replaced by -# the job ID). -#SBATCH --error=horovod-%j.err -# if keyword omitted: Default is slurm-%j.out in -# the submission directory. -#SBATCH --time=20:00:00 -#SBATCH --gres=gpu:4 -#SBATCH --partition=gpus -#SBATCH --mail-user=b.gong@fz-juelich.de -#SBATCH --mail-type=ALL - -#create a folder to save the output -jutil env activate -p deepacf -module --force purge -module load Stages/Devel-2019a -module load GCC/8.3.0 -module load MVAPICH2/2.3.2-GDR -module load Stages/2019a -module load Horovod/0.16.2-GPU-Python-3.6.8 -module load Keras/2.2.4-GPU-Python-3.6.8 - -#module load ParaStationMPI/5.2.2-1 -#module load h5py/2.9.0-Python-3.6.8 -# *** start of job script ***: -# Note: The current working directory at this point is -# the directory where sbatch was executed. -# export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} -# *** start of job script *** -# Note: The current working directory at this point is -# the directory where sbatch was executed. -# export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} -srun --cpu_bind=none python3.6 kitti_train_horovod.py diff --git a/workflow_parallel_frame_prediction/Training/keras_utils.py b/workflow_parallel_frame_prediction/Training/keras_utils.py deleted file mode 100755 index ededcc74..00000000 --- a/workflow_parallel_frame_prediction/Training/keras_utils.py +++ /dev/null @@ -1,58 +0,0 @@ -import os -import numpy as np - -from keras import backend as K -from keras.legacy.interfaces import generate_legacy_interface, recurrent_args_preprocessor -from keras.models import model_from_json - -legacy_prednet_support = generate_legacy_interface( - allowed_positional_args=['stack_sizes', 'R_stack_sizes', - 'A_filt_sizes', 'Ahat_filt_sizes', 'R_filt_sizes'], - conversions=[('dim_ordering', 'data_format'), - ('consume_less', 'implementation')], - value_conversions={'dim_ordering': {'tf': 'channels_last', - 'th': 'channels_first', - 'default': None}, - 'consume_less': {'cpu': 0, - 'mem': 1, - 'gpu': 2}}, - preprocessor=recurrent_args_preprocessor) - -# Convert old Keras (1.2) json models and weights to Keras 2.0 -def convert_model_to_keras2(old_json_file, old_weights_file, new_json_file, new_weights_file): - from prednet import PredNet - # If using tensorflow, it doesn't allow you to load the old weights. - if K.backend() != 'theano': - os.environ['KERAS_BACKEND'] = backend - reload(K) - - f = open(old_json_file, 'r') - json_string = f.read() - f.close() - model = model_from_json(json_string, custom_objects = {'PredNet': PredNet}) - model.load_weights(old_weights_file) - - weights = model.layers[1].get_weights() - if weights[0].shape[0] == model.layers[1].stack_sizes[1]: - for i, w in enumerate(weights): - if w.ndim == 4: - weights[i] = np.transpose(w, (2, 3, 1, 0)) - model.set_weights(weights) - - model.save_weights(new_weights_file) - json_string = model.to_json() - with open(new_json_file, "w") as f: - f.write(json_string) - - -if __name__ == '__main__': - old_dir = './model_data/' - new_dir = './model_data_keras2/' - if not os.path.exists(new_dir): - os.mkdir(new_dir) - for w_tag in ['', '-Lall', '-extrapfinetuned']: - m_tag = '' if w_tag == '-Lall' else w_tag - convert_model_to_keras2(old_dir + 'prednet_kitti_model' + m_tag + '.json', - old_dir + 'prednet_kitti_weights' + w_tag + '.hdf5', - new_dir + 'prednet_kitti_model' + m_tag + '.json', - new_dir + 'prednet_kitti_weights' + w_tag + '.hdf5') diff --git a/workflow_parallel_frame_prediction/Training/kitti_settings.py b/workflow_parallel_frame_prediction/Training/kitti_settings.py deleted file mode 100755 index 54767111..00000000 --- a/workflow_parallel_frame_prediction/Training/kitti_settings.py +++ /dev/null @@ -1,19 +0,0 @@ -# Where KITTI data will be saved if you run process_kitti.py -# If you directly download the processed data, change to the path of the data. -## Changed logic: Now this is the path where the processed data lies: X_train,val,test -#DATA_DIR = './kitti_data/' -#data directory for training data 2015 and 2016 -#DATA_DIR = '/p/project/cjjsc42/severin/try3' -#data directory for moving objects: -#DATA_DIR = '/p/home/jusers/hussmann1/jureca/movingObjects/se_nw' -#data directory for featuretesting: -##DATA_DIR = './testTry2' -DATA_DIR = '/p/scratch/cjjsc42/bing/PredNet/processData/splits' -# Where model weights and config will be saved if you run kitti_train.py -# If you directly download the trained weights, change to appropriate path. -WEIGHTS_DIR = './model_data_keras2/' -#WEIGHTS_DIR = '/p/project/cjjsc42/bing/ml-severin/model_data_keras2' - -# Where results (prediction plots and evaluation file) will be saved. -#RESULTS_SAVE_DIR = './kitti_results' - diff --git a/workflow_parallel_frame_prediction/Training/kitti_train_horovod.py b/workflow_parallel_frame_prediction/Training/kitti_train_horovod.py deleted file mode 100755 index 72539927..00000000 --- a/workflow_parallel_frame_prediction/Training/kitti_train_horovod.py +++ /dev/null @@ -1,119 +0,0 @@ -''' -Train PredNet on KITTI sequences. (Geiger et al. 2013, http://www.cvlibs.net/datasets/kitti/) -''' - -import os -import numpy as np -np.random.seed(123) -#from six.moves import cPickle - -from keras import backend as K -from keras.models import Model -from keras.layers import Input, Dense, Flatten -from keras.layers import LSTM -from keras.layers import TimeDistributed -from keras.callbacks import LearningRateScheduler, ModelCheckpoint -from keras.optimizers import Adam -from prednet import PredNet -from data_utils import SequenceGenerator -from kitti_settings import * -import datetime -import horovod.keras as hvd -import keras -import tensorflow as tf -#Horovod:initialize horovod -hvd.init() -#Horovod: pin GPU to be used for process local rank (one GPU per process) -config = tf.ConfigProto() -config.gpu_options.allow_growth = True -config.gpu_options.visible_device_list = str(hvd.local_rank()) -K.set_session(tf.Session(config=config)) - -print("horovode size", hvd.size()) - -save_model = True# if weights will be saved -weights_file = os.path.join(WEIGHTS_DIR, 'prednet_kitti_weights.hdf5') # where weights will be saved -json_file = os.path.join(WEIGHTS_DIR, 'prednet_kitti_model.json') -if not os.path.exists(WEIGHTS_DIR): os.mkdir(WEIGHTS_DIR) -# Data files -train_file = os.path.join(DATA_DIR, 'X_train.hkl') -train_sources = os.path.join(DATA_DIR, 'sources_train.hkl') -val_file = os.path.join(DATA_DIR, 'X_val.hkl') -val_sources = os.path.join(DATA_DIR, 'sources_val.hkl') - -# Training parameters -nb_epoch = 10 #original: 150; for all tests so far set to 100; t2onlyMax: 150 -batch_size = 15 -samples_per_epoch = 500 #original: 500; for all tests so far set to 300; t2onlyMax: 500 -N_seq_val = 80 # number of sequences to use for validation ##original: 100; for all tests so far set to 65; t2onlyMax: 80 - -# Model parameters -n_channels, im_height, im_width = (3, 128, 160) -input_shape = (n_channels, im_height, im_width) if K.image_data_format() == 'channels_first' else (im_height, im_width, n_channels) -stack_sizes = (n_channels, 48, 96, 192) -R_stack_sizes = stack_sizes -A_filt_sizes = (3, 3, 3) -Ahat_filt_sizes = (3, 3, 3, 3) -R_filt_sizes = (3, 3, 3, 3) -layer_loss_weights = np.array([1., 0., 0., 0.]) # weighting for each layer in final loss; "L_0" model: [1, 0, 0, 0], "L_all": [1, 0.1, 0.1, 0.1] -layer_loss_weights = np.expand_dims(layer_loss_weights, 1) -nt = 10 # number of timesteps used for sequences in training -time_loss_weights = 1./ (nt - 1) * np.ones((nt,1)) # equally weight all timesteps except the first -time_loss_weights[0] = 0 - -prednet = PredNet(stack_sizes, R_stack_sizes, - A_filt_sizes, Ahat_filt_sizes, R_filt_sizes, - output_mode='error', return_sequences=True) -inputs = Input(shape=(nt,) + input_shape) -errors = prednet(inputs) # errors will be (batch_size, nt, nb_layers) -errors_by_time = TimeDistributed(Dense(1, trainable=False), weights=[layer_loss_weights, np.zeros(1)], trainable=False)(errors) # calculate weighted error by layer -errors_by_time = Flatten()(errors_by_time) # will be (batch_size, nt) -final_errors = Dense(1, weights=[time_loss_weights, np.zeros(1)], trainable=False)(errors_by_time) # weight errors by time -model = Model(inputs=inputs, outputs=final_errors) -#Horovod:ajust learning rate based on number of GPUs -opt = keras.optimizers.Adam(0.01 * hvd.size()) -#Horovod: add horovod DistributedOptimizer -opt = hvd.DistributedOptimizer(opt) -#Horovode: use hvd.DistributedOptimizer to compute gradients -model.compile(loss="mean_absolute_error", optimizer=opt, metrics=["accuracy"]) - - - -train_generator = SequenceGenerator(train_file, train_sources, nt, batch_size=batch_size, shuffle=True) -val_generator = SequenceGenerator(val_file, val_sources, nt, batch_size=batch_size, N_seq=N_seq_val) - -#lr_schedule = lambda epoch: 0.001 if epoch < 75 else 0.0001 # start with lr of 0.001 and then drop to 0.0001 after 75 epochs -callbacks = [hvd.callbacks.BroadcastGlobalVariablesCallback(0), - #hvd.callbacks.MetricAverageCallback(), - hvd.callbacks.LearningRateWarmupCallback(warmup_epochs=5,verbose=1) - ] -#bing: original save_model is True -if hvd.rank() == 0: - if save_model: - print("===========The model will be saved =======") - callbacks.append(ModelCheckpoint(filepath=weights_file, monitor='val_loss', save_best_only=True)) - -#the start training time -a = datetime.datetime.now() - -history = model.fit_generator(generator=train_generator,steps_per_epoch=samples_per_epoch/(batch_size*hvd.size()), epochs=nb_epoch, callbacks=callbacks, - validation_data=val_generator, validation_steps=N_seq_val/(batch_size*hvd.size())) - - -b = datetime.datetime.now() - -#the training time -t = b-a - -stats = list(train_generator.X.shape) -stats.append(t) - -print("training time is",stats) - -if save_model: - json_string = model.to_json() - with open(json_file, "w") as f: - f.write(json_string) - - - diff --git a/workflow_parallel_frame_prediction/Training/minMaxExtractor.py b/workflow_parallel_frame_prediction/Training/minMaxExtractor.py deleted file mode 100644 index 5c121620..00000000 --- a/workflow_parallel_frame_prediction/Training/minMaxExtractor.py +++ /dev/null @@ -1,76 +0,0 @@ -import hickle as hkl -import numpy as np -import matplotlib.pyplot as plt - -#x_train = hkl.load('/Users/Severin/Desktop/X_train.hkl') #load X_train produces on jureca -x_train = hkl.load('/p/project/cjjsc42/severin/try3/X_train.hkl') #load X_train produces on jureca -print('Shape of X:') -print(x_train.shape) -print('') - -#Print example -#t2_cutout = x_train[100,:,:,0] -#printt2cutout = plt.pcolormesh(t2_cutout[::-1,:], shading='bottom', cmap=plt.cm.jet) -#plt.savefig('t2_cutout') -#Extract Max min values: -maxT2 = np.amax(x_train[:,:,:,0]) # numpy.amax() returns the maximum of an array or maximum along an axis. -print('maxT2: ' + str(maxT2)) -minT2 = np.amin(x_train[:,:,:,0]) -print('minT2: ' + str(minT2)) -meanT2 = np.mean(x_train[:,:,:,0]) -print('meanT2: ' + str(meanT2)) -stdT2 = np.std(x_train[:,:,:,0]) -print('stdT2: ' + str(stdT2)) -highCutT2 = meanT2 + 3 * stdT2 -print('highCutT2: ' + str(highCutT2)) -lowCutT2 = meanT2 - 3 * stdT2 -print('lowCutT2: ' + str(lowCutT2)) -print('') - -maxGP = np.amax(x_train[:,:,:,1]) -print('maxGP: ' + str(maxGP)) -minGP = np.amin(x_train[:,:,:,1]) -print('minGP: ' + str(minGP)) -meanGP = np.mean(x_train[:,:,:,1]) -print('meanGP: ' + str(meanGP)) -stdGP = np.std(x_train[:,:,:,1]) -print('stdGP: ' + str(stdGP)) -highCutGP = meanGP + 3 * stdGP -print('highCutGP: ' + str(highCutGP)) -lowCutGP = meanGP - 3 * stdGP -print('lowCutGP: ' + str(lowCutGP)) -print('') - -maxGPH = np.amax(x_train[:,:,:,2]) -print('maxGPH: ' + str(maxGPH)) -minGPH = np.amin(x_train[:,:,:,2]) -print('minGPH: ' + str(minGPH)) -meanGPH = np.mean(x_train[:,:,:,2]) -print('meanGP: ' + str(meanGPH)) -stdGPH = np.std(x_train[:,:,:,2]) -print('stdGPH: ' + str(stdGPH)) -highCutGPH = meanGPH + 3 * stdGPH -print('highCutGPH: ' + str(highCutGPH)) -lowCutGPH = meanGPH - 3 * stdGPH -print('lowCutGPH: ' + str(lowCutGPH)) -print('') - -# Formel zum normalisieren: z = (x-min(x))/(max(x)-min(x)) -#x_trainNormalized2 = np.zeros(shape=x_train.shape) -#print('Empty shape:') -#print(x_trainNormalized2.shape) -#x_trainNormalized2[:,:,:,0] = (x_train[:,:,:,0]-minT2)/(maxT2-minT2) -#x_trainNormalized2[:,:,:,1] = (x_train[:,:,:,1]-minGP)/(maxGP-minGP) -#x_trainNormalized2[:,:,:,2] = (x_train[:,:,:,2]-minGPH)/(maxGPH-minGPH) - -#print('MaxMin values of normalized dataset:') -#print('T2:') -#print(np.amax(x_trainNormalized2[:,:,:,0])) -#print(np.amin(x_trainNormalized2[:,:,:,0])) -#print('GP:') -#print(np.amax(x_trainNormalized2[:,:,:,1])) -#print(np.amin(x_trainNormalized2[:,:,:,1])) -#print('GPH:') -#print(np.amax(x_trainNormalized2[:,:,:,2])) -#print(np.amin(x_trainNormalized2[:,:,:,2])) -#print(x_trainNormalized2) \ No newline at end of file diff --git a/workflow_parallel_frame_prediction/Training/prednet.py b/workflow_parallel_frame_prediction/Training/prednet.py deleted file mode 100755 index b5a0208a..00000000 --- a/workflow_parallel_frame_prediction/Training/prednet.py +++ /dev/null @@ -1,311 +0,0 @@ -import numpy as np - -from keras import backend as K -from keras import activations -from keras.layers import Recurrent -from keras.layers import Conv2D, UpSampling2D, MaxPooling2D -from keras.engine import InputSpec -from keras_utils import legacy_prednet_support - -class PredNet(Recurrent): - '''PredNet architecture - Lotter 2016. - Stacked convolutional LSTM inspired by predictive coding principles. - - # Arguments - stack_sizes: number of channels in targets (A) and predictions (Ahat) in each layer of the architecture. - Length is the number of layers in the architecture. - First element is the number of channels in the input. - Ex. (3, 16, 32) would correspond to a 3 layer architecture that takes in RGB images and has 16 and 32 - channels in the second and third layers, respectively. - R_stack_sizes: number of channels in the representation (R) modules. - Length must equal length of stack_sizes, but the number of channels per layer can be different. - A_filt_sizes: filter sizes for the target (A) modules. - Has length of 1 - len(stack_sizes). - Ex. (3, 3) would mean that targets for layers 2 and 3 are computed by a 3x3 convolution of the errors (E) - from the layer below (followed by max-pooling) - Ahat_filt_sizes: filter sizes for the prediction (Ahat) modules. - Has length equal to length of stack_sizes. - Ex. (3, 3, 3) would mean that the predictions for each layer are computed by a 3x3 convolution of the - representation (R) modules at each layer. - R_filt_sizes: filter sizes for the representation (R) modules. - Has length equal to length of stack_sizes. - Corresponds to the filter sizes for all convolutions in the LSTM. - pixel_max: the maximum pixel value. - Used to clip the pixel-layer prediction. - error_activation: activation function for the error (E) units. - A_activation: activation function for the target (A) and prediction (A_hat) units. - LSTM_activation: activation function for the cell and hidden states of the LSTM. - LSTM_inner_activation: activation function for the gates in the LSTM. - output_mode: either 'error', 'prediction', 'all' or layer specification (ex. R2, see below). - Controls what is outputted by the PredNet. - If 'error', the mean response of the error (E) units of each layer will be outputted. - That is, the output shape will be (batch_size, nb_layers). - If 'prediction', the frame prediction will be outputted. - If 'all', the output will be the frame prediction concatenated with the mean layer errors. - The frame prediction is flattened before concatenation. - Nomenclature of 'all' is kept for backwards compatibility, but should not be confused with returning all of the layers of the model - For returning the features of a particular layer, output_mode should be of the form unit_type + layer_number. - For instance, to return the features of the LSTM "representational" units in the lowest layer, output_mode should be specificied as 'R0'. - The possible unit types are 'R', 'Ahat', 'A', and 'E' corresponding to the 'representation', 'prediction', 'target', and 'error' units respectively. - extrap_start_time: time step for which model will start extrapolating. - Starting at this time step, the prediction from the previous time step will be treated as the "actual" - data_format: 'channels_first' or 'channels_last'. - It defaults to the `image_data_format` value found in your - Keras config file at `~/.keras/keras.json`. - - # References - - [Deep predictive coding networks for video prediction and unsupervised learning](https://arxiv.org/abs/1605.08104) - - [Long short-term memory](http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf) - - [Convolutional LSTM network: a machine learning approach for precipitation nowcasting](http://arxiv.org/abs/1506.04214) - - [Predictive coding in the visual cortex: a functional interpretation of some extra-classical receptive-field effects](http://www.nature.com/neuro/journal/v2/n1/pdf/nn0199_79.pdf) - ''' - @legacy_prednet_support - def __init__(self, stack_sizes, R_stack_sizes, - A_filt_sizes, Ahat_filt_sizes, R_filt_sizes, - pixel_max=1., error_activation='relu', A_activation='relu', - LSTM_activation='tanh', LSTM_inner_activation='hard_sigmoid', - output_mode='error', extrap_start_time=None, - data_format=K.image_data_format(), **kwargs): - self.stack_sizes = stack_sizes - self.nb_layers = len(stack_sizes) - assert len(R_stack_sizes) == self.nb_layers, 'len(R_stack_sizes) must equal len(stack_sizes)' - self.R_stack_sizes = R_stack_sizes - assert len(A_filt_sizes) == (self.nb_layers - 1), 'len(A_filt_sizes) must equal len(stack_sizes) - 1' - self.A_filt_sizes = A_filt_sizes - assert len(Ahat_filt_sizes) == self.nb_layers, 'len(Ahat_filt_sizes) must equal len(stack_sizes)' - self.Ahat_filt_sizes = Ahat_filt_sizes - assert len(R_filt_sizes) == (self.nb_layers), 'len(R_filt_sizes) must equal len(stack_sizes)' - self.R_filt_sizes = R_filt_sizes - - self.pixel_max = pixel_max - self.error_activation = activations.get(error_activation) - self.A_activation = activations.get(A_activation) - self.LSTM_activation = activations.get(LSTM_activation) - self.LSTM_inner_activation = activations.get(LSTM_inner_activation) - - default_output_modes = ['prediction', 'error', 'all'] - layer_output_modes = [layer + str(n) for n in range(self.nb_layers) for layer in ['R', 'E', 'A', 'Ahat']] - assert output_mode in default_output_modes + layer_output_modes, 'Invalid output_mode: ' + str(output_mode) - self.output_mode = output_mode - if self.output_mode in layer_output_modes: - self.output_layer_type = self.output_mode[:-1] - self.output_layer_num = int(self.output_mode[-1]) - else: - self.output_layer_type = None - self.output_layer_num = None - self.extrap_start_time = extrap_start_time - - assert data_format in {'channels_last', 'channels_first'}, 'data_format must be in {channels_last, channels_first}' - self.data_format = data_format - self.channel_axis = -3 if data_format == 'channels_first' else -1 - self.row_axis = -2 if data_format == 'channels_first' else -3 - self.column_axis = -1 if data_format == 'channels_first' else -2 - super(PredNet, self).__init__(**kwargs) - self.input_spec = [InputSpec(ndim=5)] - - def compute_output_shape(self, input_shape): - if self.output_mode == 'prediction': - out_shape = input_shape[2:] - elif self.output_mode == 'error': - out_shape = (self.nb_layers,) - elif self.output_mode == 'all': - out_shape = (np.prod(input_shape[2:]) + self.nb_layers,) - else: - stack_str = 'R_stack_sizes' if self.output_layer_type == 'R' else 'stack_sizes' - stack_mult = 2 if self.output_layer_type == 'E' else 1 - out_stack_size = stack_mult * getattr(self, stack_str)[self.output_layer_num] - out_nb_row = input_shape[self.row_axis] / 2**self.output_layer_num - out_nb_col = input_shape[self.column_axis] / 2**self.output_layer_num - if self.data_format == 'channels_first': - out_shape = (out_stack_size, out_nb_row, out_nb_col) - else: - out_shape = (out_nb_row, out_nb_col, out_stack_size) - - if self.return_sequences: - return (input_shape[0], input_shape[1]) + out_shape - else: - return (input_shape[0],) + out_shape - - def get_initial_state(self, x): - input_shape = self.input_spec[0].shape - init_nb_row = input_shape[self.row_axis] - init_nb_col = input_shape[self.column_axis] - - base_initial_state = K.zeros_like(x) # (samples, timesteps) + image_shape - non_channel_axis = -1 if self.data_format == 'channels_first' else -2 - for _ in range(2): - base_initial_state = K.sum(base_initial_state, axis=non_channel_axis) - base_initial_state = K.sum(base_initial_state, axis=1) # (samples, nb_channels) - - initial_states = [] - states_to_pass = ['r', 'c', 'e'] - nlayers_to_pass = {u: self.nb_layers for u in states_to_pass} - if self.extrap_start_time is not None: - states_to_pass.append('ahat') # pass prediction in states so can use as actual for t+1 when extrapolating - nlayers_to_pass['ahat'] = 1 - for u in states_to_pass: - for l in range(nlayers_to_pass[u]): - ds_factor = 2 ** l - nb_row = init_nb_row // ds_factor - nb_col = init_nb_col // ds_factor - if u in ['r', 'c']: - stack_size = self.R_stack_sizes[l] - elif u == 'e': - stack_size = 2 * self.stack_sizes[l] - elif u == 'ahat': - stack_size = self.stack_sizes[l] - output_size = stack_size * nb_row * nb_col # flattened size - - reducer = K.zeros((input_shape[self.channel_axis], output_size)) # (nb_channels, output_size) - initial_state = K.dot(base_initial_state, reducer) # (samples, output_size) - if self.data_format == 'channels_first': - output_shp = (-1, stack_size, nb_row, nb_col) - else: - output_shp = (-1, nb_row, nb_col, stack_size) - initial_state = K.reshape(initial_state, output_shp) - initial_states += [initial_state] - - if K._BACKEND == 'theano': - from theano import tensor as T - # There is a known issue in the Theano scan op when dealing with inputs whose shape is 1 along a dimension. - # In our case, this is a problem when training on grayscale images, and the below line fixes it. - initial_states = [T.unbroadcast(init_state, 0, 1) for init_state in initial_states] - - if self.extrap_start_time is not None: - initial_states += [K.variable(0, int if K.backend() != 'tensorflow' else 'int32')] # the last state will correspond to the current timestep - return initial_states - - def build(self, input_shape): - self.input_spec = [InputSpec(shape=input_shape)] - self.conv_layers = {c: [] for c in ['i', 'f', 'c', 'o', 'a', 'ahat']} - - for l in range(self.nb_layers): - for c in ['i', 'f', 'c', 'o']: - act = self.LSTM_activation if c == 'c' else self.LSTM_inner_activation - self.conv_layers[c].append(Conv2D(self.R_stack_sizes[l], self.R_filt_sizes[l], padding='same', activation=act, data_format=self.data_format)) - - act = 'relu' if l == 0 else self.A_activation - self.conv_layers['ahat'].append(Conv2D(self.stack_sizes[l], self.Ahat_filt_sizes[l], padding='same', activation=act, data_format=self.data_format)) - - if l < self.nb_layers - 1: - self.conv_layers['a'].append(Conv2D(self.stack_sizes[l+1], self.A_filt_sizes[l], padding='same', activation=self.A_activation, data_format=self.data_format)) - - self.upsample = UpSampling2D(data_format=self.data_format) - self.pool = MaxPooling2D(data_format=self.data_format) - - self.trainable_weights = [] - nb_row, nb_col = (input_shape[-2], input_shape[-1]) if self.data_format == 'channels_first' else (input_shape[-3], input_shape[-2]) - for c in sorted(self.conv_layers.keys()): - for l in range(len(self.conv_layers[c])): - ds_factor = 2 ** l - if c == 'ahat': - nb_channels = self.R_stack_sizes[l] - elif c == 'a': - nb_channels = 2 * self.stack_sizes[l] - else: - nb_channels = self.stack_sizes[l] * 2 + self.R_stack_sizes[l] - if l < self.nb_layers - 1: - nb_channels += self.R_stack_sizes[l+1] - in_shape = (input_shape[0], nb_channels, nb_row // ds_factor, nb_col // ds_factor) - if self.data_format == 'channels_last': in_shape = (in_shape[0], in_shape[2], in_shape[3], in_shape[1]) - with K.name_scope('layer_' + c + '_' + str(l)): - self.conv_layers[c][l].build(in_shape) - self.trainable_weights += self.conv_layers[c][l].trainable_weights - - self.states = [None] * self.nb_layers*3 - - if self.extrap_start_time is not None: - self.t_extrap = K.variable(self.extrap_start_time, int if K.backend() != 'tensorflow' else 'int32') - self.states += [None] * 2 # [previous frame prediction, timestep] - - def step(self, a, states): - r_tm1 = states[:self.nb_layers] - c_tm1 = states[self.nb_layers:2*self.nb_layers] - e_tm1 = states[2*self.nb_layers:3*self.nb_layers] - - if self.extrap_start_time is not None: - t = states[-1] - a = K.switch(t >= self.t_extrap, states[-2], a) # if past self.extrap_start_time, the previous prediction will be treated as the actual - - c = [] - r = [] - e = [] - - # Update R units starting from the top - for l in reversed(range(self.nb_layers)): - inputs = [r_tm1[l], e_tm1[l]] - if l < self.nb_layers - 1: - inputs.append(r_up) - - inputs = K.concatenate(inputs, axis=self.channel_axis) - i = self.conv_layers['i'][l].call(inputs) - f = self.conv_layers['f'][l].call(inputs) - o = self.conv_layers['o'][l].call(inputs) - _c = f * c_tm1[l] + i * self.conv_layers['c'][l].call(inputs) - _r = o * self.LSTM_activation(_c) - c.insert(0, _c) - r.insert(0, _r) - - if l > 0: - r_up = self.upsample.call(_r) - - # Update feedforward path starting from the bottom - for l in range(self.nb_layers): - ahat = self.conv_layers['ahat'][l].call(r[l]) - if l == 0: - ahat = K.minimum(ahat, self.pixel_max) - frame_prediction = ahat - - # compute errors - e_up = self.error_activation(ahat - a) - e_down = self.error_activation(a - ahat) - - e.append(K.concatenate((e_up, e_down), axis=self.channel_axis)) - - if self.output_layer_num == l: - if self.output_layer_type == 'A': - output = a - elif self.output_layer_type == 'Ahat': - output = ahat - elif self.output_layer_type == 'R': - output = r[l] - elif self.output_layer_type == 'E': - output = e[l] - - if l < self.nb_layers - 1: - a = self.conv_layers['a'][l].call(e[l]) - a = self.pool.call(a) # target for next layer - - if self.output_layer_type is None: - if self.output_mode == 'prediction': - output = frame_prediction - else: - for l in range(self.nb_layers): - layer_error = K.mean(K.batch_flatten(e[l]), axis=-1, keepdims=True) - all_error = layer_error if l == 0 else K.concatenate((all_error, layer_error), axis=-1) - if self.output_mode == 'error': - output = all_error - else: - output = K.concatenate((K.batch_flatten(frame_prediction), all_error), axis=-1) - - states = r + c + e - if self.extrap_start_time is not None: - states += [frame_prediction, t + 1] - return output, states - - def get_config(self): - config = {'stack_sizes': self.stack_sizes, - 'R_stack_sizes': self.R_stack_sizes, - 'A_filt_sizes': self.A_filt_sizes, - 'Ahat_filt_sizes': self.Ahat_filt_sizes, - 'R_filt_sizes': self.R_filt_sizes, - 'pixel_max': self.pixel_max, - 'error_activation': self.error_activation.__name__, - 'A_activation': self.A_activation.__name__, - 'LSTM_activation': self.LSTM_activation.__name__, - 'LSTM_inner_activation': self.LSTM_inner_activation.__name__, - 'data_format': self.data_format, - 'extrap_start_time': self.extrap_start_time, - 'output_mode': self.output_mode} - base_config = super(PredNet, self).get_config() - return dict(list(base_config.items()) + list(config.items())) diff --git a/workflow_parallel_frame_prediction/Training/process_netCDF.py b/workflow_parallel_frame_prediction/Training/process_netCDF.py deleted file mode 100644 index 2cb822ec..00000000 --- a/workflow_parallel_frame_prediction/Training/process_netCDF.py +++ /dev/null @@ -1,169 +0,0 @@ -''' -Code for processing staged ERA5 data -''' - -import os -#import requests -#from bs4 import BeautifulSoup -#import urllib.request -import numpy as np -#from imageio import imread -#from scipy.misc import imresize -import hickle as hkl -from netCDF4 import Dataset -from kitti_settings import * - -#TODO: Not optimal with DATA_DIR and filingPath: In original process_kitti.py -# there's just DATA_DIR (which is specified in kitti_settings.py) and in there -# the processed data will be stores. The raw data lies also in there in a subfolder - -#Path of ERA5 Data -DATA_DIR = './testData2' -print(DATA_DIR) -#Path where to save processed data -filingPath = './testTry2' - -# ToDo: Define a convenient function to create a list containing all files. -imageList = list(os.walk(DATA_DIR, topdown=False))[-1][-1] -imageList = sorted(imageList) -print('Image List:') -print(imageList) -print('Length of Image List: ' + str(len(imageList))) -#scp hussmann1@jureca.fz-juelich.de:/p/project/cjjsc42/severin/data/era5_extract_481.nc ~/Desktop/netCDFdata - -# ToDo: Define properly the train, val and test index -# Here just for testing and taking weird .DS_Store file into consideration -# http://www.apfelwiki.de/Main/DSStore -#train_recordings = imageList[1:6] -#val_recordings = imageList[7:9] -#test_recordings = imageList[-2:] - -#Train,Val,Test size in percentage -partition = [0.8, 0.05, 0.15] -#determine correct indices -train_begin = 0 -train_end = round(partition[0]*len(imageList))-1 -val_begin = train_end + 1 -val_end = train_end + round(partition[1]*len(imageList)) -test_begin = val_end + 1 -test_end = len(imageList)-1 -print('Indices of Train, Val and test: '+ str(train_begin) + ' ' + str(val_begin) + ' ' + str(test_begin)) -#slightly adapting start and end because starts at the first index given and stops before(!) the last. -train_recordings = imageList[train_begin:val_begin] -val_recordings = imageList[val_begin:test_begin] -test_recordings = imageList[test_begin:test_end] - -#adapted for feature testing: just first year (2015); Otherwise would take too long and some weird mistake in some data in 2016 -#in total: 17544 -#half: 8772 -#train: 0-6900 -#val:6901-7000 -#test:7001-8772 -#train_recordings = imageList[0:1000] -#val_recordings = imageList[6901:7000] -#test_recordings = imageList[7001:8772] - -print('Now everything together:') -print('Train:') -print(train_recordings) -print('Val:') -print(val_recordings) -print('Test:') -print(test_recordings) - -desired_im_sz = (128, 160) -# Create image datasets. -# Processes images and saves them in train, val, test splits. -def process_data(): - splits = {s: [] for s in ['train', 'test', 'val']} - splits['val'] = val_recordings - splits['test'] = test_recordings - splits['train'] = train_recordings - for split in splits: - source_list = [DATA_DIR] * len(splits[split]) # corresponds to recording that image came from - print(splits[split]) - print(source_list) - print((len(splits[split])==(len(source_list)))) - print('The list of ' + split + ' has length: ' + str(len(source_list))) - print( 'Creating ' + split + ' data: ' + str(len(source_list)) + ' images') - - #X = np.zeros((len(splits[split]),) + desired_im_sz + (3,), np.uint8) - #print(X) - #print('shape of X' + str(X.shape)) - - ##### TODO: iterate over split and read every .nc file, cut out array, - ##### overlay arrays for RGB like style. - ##### Save everything after for loop. - EU_stack_list = [0] * (len(splits[split])) - - for i, im_file in enumerate(splits[split]): - im_path = os.path.join(DATA_DIR, im_file) - print('Open following dataset: ' + im_path) - im = Dataset(im_path, mode = 'r') - #print(im) - t2 = im.variables['T2'][0,:,:] - msl = im.variables['MSL'][0,:,:] - gph500 = im.variables['gph500'][0,:,:] - im.close() - EU_t2 = t2[74:202, 550:710] - EU_msl = msl[74:202, 550:710] - EU_gph500 = gph500[74:202, 550:710] - print(EU_t2.shape, EU_msl.shape, EU_gph500.shape) - #Normal stack: T2, MSL & GPH500 - #EU_stack = np.stack([EU_t2, EU_msl, EU_gph500],axis=2) - #Stack T2 only: - #EU_stack = np.stack([EU_t2, EU_t2, EU_t2],axis=2) - #EU_stack_list[i]=EU_stack - #Stack T2*2 MSL*1: - #EU_stack = np.stack([EU_t2, EU_t2, EU_msl],axis=2) - #EU_stack_list[i]=EU_stack - #EU_stack = np.stack([EU_t2, EU_msl, EU_msl],axis=2) - #EU_stack_list[i]=EU_stack - #Stack T2*2 gph500*1: - #EU_stack = np.stack([EU_t2, EU_t2, EU_gph500],axis=2) - #EU_stack_list[i]=EU_stack - #Stack T2*1 gph500*2 - #EU_stack = np.stack([EU_t2, EU_gph500, EU_gph500],axis=2) - #EU_stack_list[i]=EU_stack - #print(EU_stack.shape) - #X[i]=EU_stack #this should be unnecessary - #t2_1 stack. Stack t2 with two empty arrays - #empty_image = np.zeros(shape = (128, 160)) - #EU_stack = np.stack([EU_t2, empty_image, empty_image],axis=2) - #EU_stack_list[i]=EU_stack - #t2_2 stack. Stack t2 with one empty array - empty_image = np.zeros(shape = (128, 160)) - EU_stack = np.stack([EU_t2, EU_t2, empty_image],axis=2) - EU_stack_list[i]=EU_stack - #print('Does ist work? ') - #print(EU_stack_list[i][:,:,0]==EU_t2) - #print(EU_stack[:,:,1]==EU_msl) - X = np.array(EU_stack_list) - print('Shape of X: ' + str(X.shape)) - hkl.dump(X, os.path.join(filingPath, 'X_' + split + '.hkl')) #Not optimal! - hkl.dump(source_list, os.path.join(filingPath, 'sources_' + split + '.hkl')) - - - #for category, folder in splits[split]: - # im_dir = os.path.join(DATA_DIR, 'raw/', category, folder, folder[:10], folder, 'image_03/data/') - # files = list(os.walk(im_dir, topdown=False))[-1][-1] - # im_list += [im_dir + f for f in sorted(files)] - # multiply path of respective recording with lengths of its files in order to ensure - # that each entry in X_train.hkl corresponds with an entry of source_list/ sources_train.hkl - # source_list += [category + '-' + folder] * len(files) - - #print( 'Creating ' + split + ' data: ' + str(len(im_list)) + ' images') - #X = np.zeros((len(im_list),) + desired_im_sz + (3,), np.uint8) - # enumerate allows us to loop over something and have an automatic counter - #for i, im_file in enumerate(im_list): - # im = imread(im_file) - # X[i] = process_im(im, desired_im_sz) - - #hkl.dump(X, os.path.join(DATA_DIR, 'X_' + split + '.hkl')) - #hkl.dump(source_list, os.path.join(DATA_DIR, 'sources_' + split + '.hkl')) - - -if __name__ == '__main__': - #download_data() - #extract_data() - process_data() diff --git a/workflow_parallel_frame_prediction/Workflow.png b/workflow_parallel_frame_prediction/Workflow.png deleted file mode 100644 index 5edc5ed807f496597f52d978d2cd28532e689b2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195317 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%0Db=jCSaG7E7v{cU>ret4K<@lpRH#Xq0)$UZZY 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	)h!b}|5ybddBC1(#J2X!K3#c{ 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 LtDnm{r-UW|NT^zK diff --git a/workflow_parallel_frame_prediction/__init__.py b/workflow_parallel_frame_prediction/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/workflow_parallel_frame_prediction/main.sh b/workflow_parallel_frame_prediction/main.sh deleted file mode 100644 index 066b202d..00000000 --- a/workflow_parallel_frame_prediction/main.sh +++ /dev/null @@ -1,28 +0,0 @@ - -#!/bin/bash -EXTRACT_PATH="./DataExtraction/Stager_devel_N_24_Bing.sh" -PREPROCESS_PATH="./DataPreprocess/Stager_devel_N_24_process_netCDF.sh" -TRAINING_PATH="./Training/horovodJob.sh" -POSPROCESS_PATH = "./DataPostprocess/Stager_devel_N_24_evaluation.sh" - -echo "============ Parallel Data Extraction ==========\n" - -sbatch "$EXTRACT_PATH" - -echo "============= Parallel Data Preprocessing =========\n " - - -sbatch "$PREPROCESS_PATH" - - -echo "============= Parallel Training ================\n" - -sbatch "$TRAINING_PATH" - - -echo "=============Parallel Postprocessing ===============\n" - -sbatch "$POSTPROCESS_PATH" - - - diff --git a/workflow_parallel_frame_prediction/setup.py b/workflow_parallel_frame_prediction/setup.py deleted file mode 100755 index 207b869d..00000000 --- a/workflow_parallel_frame_prediction/setup.py +++ /dev/null @@ -1,11 +0,0 @@ - -from setuptools import setup - -setup( - name='Parallel_Workflow_PredNet', - author="Bing,Gong; Amirpasha Mozaffari, Severin Hussman", - description="This is the parallel workflow for PredNet", - copyright= "Copyright 2019, The ESDE project", - version='1.0.0', - author_email="b.gong@fz-juelich.de", -) -- GitLab