diff --git a/.gitignore b/.gitignore index fb0457c..d9cb896 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ public/* ### Python execution ### scripts/__pycache__/ +tests/output/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..dbf1179 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +# From here: https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/use-conda-with-travis-ci.html +language: python +python: + # We don't actually use the Travis Python, but this keeps it organized. + - "3.7" + - "3.8" +install: + # Install phase of our CI pipeline + - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh + - bash miniconda.sh -b -p $HOME/miniconda + - source "$HOME/miniconda/etc/profile.d/conda.sh" + - hash -r + - conda config --set always_yes yes --set changeps1 no + - conda update -q conda + - conda info -a + - conda create -q -n project python=$TRAVIS_PYTHON_VERSION -c plotly --file requirements.txt + - conda activate project + +script: + # Run phase of our CI pipeline + - make unitTests + - make doc + +deploy: + - provider: pages:git + verbose: true + edge: true + token: $GITHUB_TOKEN + local_dir: ./public/ + on: + branch: master + condition: $TRAVIS_PYTHON_VERSION = 3.8 \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile index 8f4743e..84e336a 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -37,5 +37,6 @@ html: gendocs mkdir -p $(OUTPUTDIR)/html/ cp -R $(BUILDDIR)/html/* $(OUTPUTDIR) @echo "html files copied; the html files are in $(OUTPUTDIR)." + touch $(OUTPUTDIR)/.nojekyll diff --git a/docs/source/modules.rst b/docs/source/modules.rst index 99f0960..e1732b7 100644 --- a/docs/source/modules.rst +++ b/docs/source/modules.rst @@ -8,4 +8,4 @@ scripts analysis database download_data - test + paper diff --git a/docs/source/test.rst b/docs/source/paper.rst similarity index 53% rename from docs/source/test.rst rename to docs/source/paper.rst index 206500f..71f7d15 100644 --- a/docs/source/test.rst +++ b/docs/source/paper.rst @@ -1,7 +1,7 @@ -test module -=========== +paper module +============ -.. automodule:: test +.. automodule:: paper :members: :undoc-members: :show-inheritance: diff --git a/makefile b/makefile new file mode 100644 index 0000000..3e6bad7 --- /dev/null +++ b/makefile @@ -0,0 +1,22 @@ +TESTDIR = tests +SCRIPTDIR = scripts + +default: + echo "Welcome to M05 mini project" + +.PHONY: loadData +loadData: + # todo + +.PHONY: unitTests +unitTests: cleanTests + nosetests --nocapture -v "$(TESTDIR)/test.py" + +.PHONY: cleanTests +cleanTests: + rm -rf "$(TESTDIR)/output" + +.PHONY: doc +doc: + $(MAKE) -C docs clean + $(MAKE) -C docs html \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 019eb3c..735bbba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ requests -sklearn -plotly.express +scikit-learn +plotly_express==0.4.1 sphinx -sphinx_rtd_theme \ No newline at end of file +sphinx_rtd_theme +nose \ No newline at end of file diff --git a/scripts/test.py b/scripts/test.py deleted file mode 100644 index 93f926f..0000000 --- a/scripts/test.py +++ /dev/null @@ -1,51 +0,0 @@ -import algorithm -import database -import analysis -import numpy as np - -def test1(): - x = np.arange(len(database.CLASSES)) - cm = np.dot(x.reshape(len(x),1), x.reshape(1,len(x))) - print(cm) - print(database.CLASSES) - analysis.plot_confusion_matrix(cm, database.CLASSES) - -def test(): - - # Import train data - train = database.get("proto1", 'train') - #print(train) - - # Prepare train data - # norm = preprocessor.estimate_norm(numpy.vstack(train)) - # train_normed = preprocessor.normalize(train, norm) - - # Train algo - model = algorithm.Model() - model.train(train) - - # Import test data - test = database.get('proto1', 'test') - - # Prepare test data - # test_normed = preprocessor.normalize(test, norm) - - # Make prediction - test_predictions = model.predict(test) - print(test_predictions) - - # Get real labels - test_labels = algorithm.make_labels(test).astype(int) - - # Get confusion matrix - cm = analysis.get_confusion_matrix(test_predictions, test_labels) - - # Plot confusion matrix - analysis.plot_confusion_matrix(cm, database.CLASSES, normalize=True) - - # Plot confusion matrix (ignore other activities) - # analysis.plot_confusion_matrix(cm[1:, 1:], database.CLASSES[1:], normalize=True) - - -if __name__ == '__main__': - test() \ No newline at end of file diff --git a/tests/inputs/not_a_zip.txt b/tests/inputs/not_a_zip.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/inputs/simpleZip.zip b/tests/inputs/simpleZip.zip new file mode 100644 index 0000000..d10b809 Binary files /dev/null and b/tests/inputs/simpleZip.zip differ diff --git a/tests/test.py b/tests/test.py new file mode 100644 index 0000000..808065d --- /dev/null +++ b/tests/test.py @@ -0,0 +1,57 @@ +import os +import sys +sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + "/../scripts/") + +import download_data +import zipfile +import requests + +import algorithm +import analysis +import numpy as np + +import nose.tools + +# Get the path of this file to easily build relative path +base_path = os.path.dirname(os.path.realpath(__file__)) + +def test_unzip_file_not_a_zip(): + path_to_zip_file = base_path + "/inputs/not_a_zip.txt" # not a zip + directory_to_extract_to = base_path # extract here + nose.tools.assert_raises(zipfile.BadZipFile, download_data.unzip_file, path_to_zip_file, directory_to_extract_to) + +def test_unzip_file_invalid_zip_path(): + path_to_zip_file = base_path + "/simpleZip.zip" # Invalid path + directory_to_extract_to = base_path # extract here + nose.tools.assert_raises(FileNotFoundError, download_data.unzip_file, path_to_zip_file, directory_to_extract_to) + +def test_unzip_file(): + path_to_zip_file = base_path + "/inputs/simpleZip.zip" + directory_to_extract_to = base_path + "/output/" # extract here + download_data.unzip_file(path_to_zip_file, directory_to_extract_to) + nose.tools.ok_(os.path.isfile(base_path + "/output/f1.txt"), msg="SimpleZip not correctly unzipped") + +def test_download_url_invalid_url(): + url = "https://invalid_url.zip" + save_path = base_path + "/output/invalid_dl.zip" + nose.tools.assert_raises(requests.exceptions.ConnectionError, download_data.download_url, url, save_path) + +def test_download_url(): + url = "https://archive.ics.uci.edu/ml/machine-learning-databases/00405/Postures.zip" # Smaller zip to test + save_path = base_path + "/output/test_dl.zip" + download_data.download_url(url, save_path) + nose.tools.ok_(os.path.isfile(save_path), msg="Dataset not correctly downloaded") + +def test_make_labels(): + X = [np.array([0, 1, 0]), np.array([2, 3]), np.array([7, 4, 6, 9])] + labels = algorithm.make_labels(X) + ref = np.array([0,0,0,1,1,2,2,2,2]) + nose.tools.ok_((labels==ref).all(), msg="{} != {}".format(labels,ref)) + +def test_get_confusion_matrix(): + prediction = [1,2,3,1,2,2,3] + true_val = [1,2,3,1,2,3,2] + cm = analysis.get_confusion_matrix(prediction, true_val) + ref = np.array([[2, 0, 0],[0, 2, 1],[0, 1, 1]]) + nose.tools.ok_((cm==ref).all(), msg="{} != {}".format(cm,ref)) +