Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

function for loading users #125

Merged
merged 7 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 2 additions & 44 deletions bcipy/gui/BCInterface.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
import subprocess
import sys

Expand All @@ -13,7 +12,7 @@
contains_whitespaces,
invalid_length,
)
from bcipy.helpers.load import load_json_parameters, load_experiments, copy_parameters
from bcipy.helpers.load import load_json_parameters, load_experiments, copy_parameters, load_users
from bcipy.helpers.parameters import DEFAULT_PARAMETERS_PATH
from bcipy.tasks.task_registry import TaskType

Expand Down Expand Up @@ -108,25 +107,13 @@ def create_experiment(self) -> None:

self.update_experiment_list()

def fast_scandir(self, directory_name: str, return_path: bool = True) -> List[str]:
"""Fast Scan Directory.

directory_name: name of the directory to be scanned
return_path: whether or not to return the scanned directories as a relative path or name.
False will return the directory name only.
"""
if return_path:
return [f.path for f in os.scandir(directory_name) if f.is_dir()]

return [f.name for f in os.scandir(directory_name) if f.is_dir()]

def update_user_list(self) -> None:
"""Updates the user_input combo box with a list of user ids based on the
data directory configured in the current parameters."""

self.user_input.clear()
self.user_input.addItem(BCInterface.default_text)
self.user_input.addItems(self.load_users())
self.user_input.addItems(load_users(self.parameters))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing all of the parameters, let's extract the data path in advance and pass it to your method!


def update_experiment_list(self) -> None:
"""Updates the experiment_input combo box with a list of experiments based on the
Expand Down Expand Up @@ -367,35 +354,6 @@ def check_user_id(self) -> bool:
return False
return True

def load_users(self) -> List[str]:
"""Load Users.

Loads user directory names below experiments from the data path defined in parameters.json
and returns them as a list.
"""
saved_users = []
data_save_loc = self.parameters['data_save_loc']

# check the directory is valid
if os.path.isdir(data_save_loc):
path = data_save_loc

elif os.path.isdir(f'bcipy/{data_save_loc}'):
path = f'bcipy/{data_save_loc}'

else:
self.logger.info('User data save location not found! Please enter a new user id.')
return saved_users

# grab all experiments in the directory and iterate over them to get the users
experiments = self.fast_scandir(path, return_path=True)

for experiment in experiments:
users = self.fast_scandir(experiment, return_path=False)
saved_users.extend(users)

return saved_users

def load_experiments(self) -> List[str]:
"""Load experiments

Expand Down
53 changes: 53 additions & 0 deletions bcipy/helpers/load.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import logging
import pickle
import json
import os
from pathlib import Path
from shutil import copyfile
from time import localtime, strftime
from tkinter import Tk
from tkinter.filedialog import askdirectory, askopenfilename

from typing import List

import numpy as np
import pandas as pd

Expand Down Expand Up @@ -227,3 +230,53 @@ def load_txt_data() -> str:
'File type unrecognized. Please use a supported text type')

return filename


def load_users(parameters: Parameters) -> List[str]:
"""Load Users.

Loads user directory names below experiments from the data path defined in parameters.json
and returns them as a list. If the save data directory is not found, this method returns an
empty list assuming no experiments have been run yet.
"""
# build a saved users list, pull out the data save location from parameters
saved_users = []
# parameters.get('data_save_loc', False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused code. We should remove this

data_save_loc = parameters['data_save_loc']

# check the directory is valid, if it is, set path as data save location
if os.path.isdir(data_save_loc):
path = data_save_loc

# check the directory is valid after adding bcipy, if it is, set path as data save location
elif os.path.isdir(f'bcipy/{data_save_loc}'):
path = f'bcipy/{data_save_loc}'

else:
log.info(f'User save data location not found at [{data_save_loc}]! Returning empty user list.')
return saved_users

# grab all experiments in the directory and iterate over them to get the users
experiments = fast_scandir(path, return_path=True)

for experiment in experiments:
users = fast_scandir(experiment, return_path=False)
# If it is a new user, append it to the saved_user list
for user in users:
if user not in saved_users:
saved_users.append(user)

return saved_users


def fast_scandir(directory_name: str, return_path: bool = True) -> List[str]:
"""Fast Scan Directory.

directory_name: name of the directory to be scanned
return_path: whether or not to return the scanned directories as a relative path or name.
False will return the directory name only.
"""
if return_path:
return [f.path for f in os.scandir(directory_name) if f.is_dir()]

return [f.name for f in os.scandir(directory_name) if f.is_dir()]
48 changes: 48 additions & 0 deletions bcipy/helpers/tests/test_load.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import unittest
import os
from unittest.mock import patch, mock_open

from collections import abc
Expand All @@ -15,6 +16,7 @@
load_experiments,
load_experiment_fields,
load_fields,
load_users,
copy_parameters)
from bcipy.helpers.parameters import Parameters
from bcipy.helpers.exceptions import InvalidExperimentException
Expand Down Expand Up @@ -161,5 +163,51 @@ def test_load_experiment_fields_raises_invalid_experiment_on_incorrectly_formatt
load_experiment_fields(invalid_experiment_field_name)


class TestUserLoad(unittest.TestCase):

def setUp(self):
# setup parameters to pass to load users method, it expects a key of data_save_loc only
self.directory_name = 'test_data_load_user'
self.parameters = {
'data_save_loc': f'{self.directory_name}/'
}

def test_user_load_with_no_directory(self):
response = load_users(self.parameters)

self.assertEqual(response, [])

def test_user_load_no_data_save_location_provided_parameters(self):
parameters = {}
with self.assertRaises(KeyError):
load_users(parameters)

def test_user_load_with_valid_directory(self):
user = 'user_001'
file_path = f'{self.directory_name}/experiment/{user}'
os.makedirs(file_path)

response = load_users(self.parameters)

# There is only one user returned
length_of_users = len(response)
self.assertTrue(length_of_users == 1)

# assert user returned is user defined above
self.assertEqual(response[0], user)
os.rmdir(file_path)

def test_user_load_with_invalid_directory(self):
# create an invalid save structure and assert expected behavior.
user = 'user_001'
file_path = f'{self.directory_name}/experiment{user}'
os.makedirs(file_path)

response = load_users(self.parameters)
length_of_users = len(response)
self.assertTrue(length_of_users == 0)
os.rmdir(file_path)


if __name__ == '__main__':
unittest.main()