# Path: brainiak/fcma/preprocessing.py
# def prepare_mvpa_data(images, conditions, mask):
#     """Prepare data for activity-based model training and prediction.
# 
#     Average the activity within epochs and z-scoring within subject.
# 
#     Parameters
#     ----------
#     images: Iterable[SpatialImage]
#         Data.
#     conditions: List[UniqueLabelConditionSpec]
#         Condition specification.
#     mask: np.ndarray
#         Mask to apply to each image.
# 
#     Returns
#     -------
#     processed_data: 2D array in shape [num_voxels, num_epochs]
#         averaged epoch by epoch processed data
#     labels: 1D array
#         contains labels of the data
#     """
#     activity_data = list(mask_images(images, mask, np.float32))
#     epoch_info = generate_epochs_info(conditions)
#     num_epochs = len(epoch_info)
#     (d1, _) = activity_data[0].shape
#     processed_data = np.empty([d1, num_epochs])
#     labels = np.empty(num_epochs)
#     subject_count = [0]  # counting the epochs per subject for z-scoring
#     cur_sid = -1
#     # averaging
#     for idx, epoch in enumerate(epoch_info):
#         labels[idx] = epoch[0]
#         if cur_sid != epoch[1]:
#             subject_count.append(0)
#             cur_sid = epoch[1]
#         subject_count[-1] += 1
#         processed_data[:, idx] = \
#             np.mean(activity_data[cur_sid][:, epoch[2]:epoch[3]],
#                     axis=1)
#     # z-scoring
#     cur_epoch = 0
#     for i in subject_count:
#         if i > 1:
#             processed_data[:, cur_epoch:cur_epoch + i] = \
#                 zscore(processed_data[:, cur_epoch:cur_epoch + i],
#                        axis=1, ddof=0)
#         cur_epoch += i
#     # if zscore fails (standard deviation is zero),
#     # set all values to be zero
#     processed_data = np.nan_to_num(processed_data)
# 
#     return processed_data, labels
# 
# Path: brainiak/io.py
# def load_images_from_dir(in_dir: Union[str, Path], suffix: str = "nii.gz",
#                          ) -> Iterable[SpatialImage]:
# def load_images(image_paths: Iterable[Union[str, Path]]
#                 ) -> Iterable[SpatialImage]:
# def load_boolean_mask(path: Union[str, Path],
#                       predicate: Callable[[np.ndarray], np.ndarray] = None
#                       ) -> np.ndarray:
# def load_labels(path: Union[str, Path]) -> List[SingleConditionSpec]:
# def save_as_nifti_file(data: np.ndarray, affine: np.ndarray,
#                        path: Union[str, Path]) -> None:


from sklearn import svm
from brainiak.fcma.preprocessing import prepare_mvpa_data
from brainiak import io
from scipy.spatial.distance import hamming
from sklearn import model_selection
import sys
import logging
import numpy as np
#from sklearn.externals import joblib

format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
# if want to output log to a file instead of outputting log to the console,
# replace "stream=sys.stdout" with "filename='fcma.log'"
logging.basicConfig(level=logging.INFO, format=format, stream=sys.stdout)
logger = logging.getLogger(__name__)

# python3 mvpa_classification.py face_scene bet.nii.gz face_scene/visual_top_mask.nii.gz face_scene/fs_epoch_labels.npy
if __name__ == '__main__':
    if len(sys.argv) != 5:
        logger.error('the number of input argument is not correct')
        sys.exit(1)

    data_dir = sys.argv[1]
    extension = sys.argv[2]
    mask_file = sys.argv[3]
    epoch_file = sys.argv[4]

    epoch_list = np.load(epoch_file)
    num_subjects = len(epoch_list)
    num_epochs_per_subj = epoch_list[0].shape[1]

    logger.info(
        'doing MVPA training and classification on %d subjects, each of which has %d epochs' %
        (num_subjects, num_epochs_per_subj)
    )

    images = io.load_images_from_dir(data_dir, extension)
    mask = io.load_boolean_mask(mask_file)

# Path: brainiak/fcma/preprocessing.py
# def prepare_mvpa_data(images, conditions, mask):
#     """Prepare data for activity-based model training and prediction.
# 
#     Average the activity within epochs and z-scoring within subject.
# 
#     Parameters
#     ----------
#     images: Iterable[SpatialImage]
#         Data.
#     conditions: List[UniqueLabelConditionSpec]
#         Condition specification.
#     mask: np.ndarray
#         Mask to apply to each image.
# 
#     Returns
#     -------
#     processed_data: 2D array in shape [num_voxels, num_epochs]
#         averaged epoch by epoch processed data
#     labels: 1D array
#         contains labels of the data
#     """
#     activity_data = list(mask_images(images, mask, np.float32))
#     epoch_info = generate_epochs_info(conditions)
#     num_epochs = len(epoch_info)
#     (d1, _) = activity_data[0].shape
#     processed_data = np.empty([d1, num_epochs])
#     labels = np.empty(num_epochs)
#     subject_count = [0]  # counting the epochs per subject for z-scoring
#     cur_sid = -1
#     # averaging
#     for idx, epoch in enumerate(epoch_info):
#         labels[idx] = epoch[0]
#         if cur_sid != epoch[1]:
#             subject_count.append(0)
#             cur_sid = epoch[1]
#         subject_count[-1] += 1
#         processed_data[:, idx] = \
#             np.mean(activity_data[cur_sid][:, epoch[2]:epoch[3]],
#                     axis=1)
#     # z-scoring
#     cur_epoch = 0
#     for i in subject_count:
#         if i > 1:
#             processed_data[:, cur_epoch:cur_epoch + i] = \
#                 zscore(processed_data[:, cur_epoch:cur_epoch + i],
#                        axis=1, ddof=0)
#         cur_epoch += i
#     # if zscore fails (standard deviation is zero),
#     # set all values to be zero
#     processed_data = np.nan_to_num(processed_data)
# 
#     return processed_data, labels
# 
# Path: brainiak/io.py
# def load_images_from_dir(in_dir: Union[str, Path], suffix: str = "nii.gz",
#                          ) -> Iterable[SpatialImage]:
# def load_images(image_paths: Iterable[Union[str, Path]]
#                 ) -> Iterable[SpatialImage]:
# def load_boolean_mask(path: Union[str, Path],
#                       predicate: Callable[[np.ndarray], np.ndarray] = None
#                       ) -> np.ndarray:
# def load_labels(path: Union[str, Path]) -> List[SingleConditionSpec]:
# def save_as_nifti_file(data: np.ndarray, affine: np.ndarray,
#                        path: Union[str, Path]) -> None:


# Path: examples/fcma/mvpa_classification.py
from sklearn import svm
from brainiak.fcma.preprocessing import prepare_mvpa_data
from brainiak import io
from scipy.spatial.distance import hamming
from sklearn import model_selection
import sys
import logging
import numpy as np

#from sklearn.externals import joblib

format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
# if want to output log to a file instead of outputting log to the console,
# replace "stream=sys.stdout" with "filename='fcma.log'"
logging.basicConfig(level=logging.INFO, format=format, stream=sys.stdout)
logger = logging.getLogger(__name__)

# python3 mvpa_classification.py face_scene bet.nii.gz face_scene/visual_top_mask.nii.gz face_scene/fs_epoch_labels.npy
if __name__ == '__main__':
    if len(sys.argv) != 5:
        logger.error('the number of input argument is not correct')
        sys.exit(1)

    data_dir = sys.argv[1]
    extension = sys.argv[2]
    mask_file = sys.argv[3]
    epoch_file = sys.argv[4]

    epoch_list = np.load(epoch_file)
    num_subjects = len(epoch_list)
    num_epochs_per_subj = epoch_list[0].shape[1]

    logger.info(
        'doing MVPA training and classification on %d subjects, each of which has %d epochs' %
        (num_subjects, num_epochs_per_subj)
    )

    images = io.load_images_from_dir(data_dir, extension)
    mask = io.load_boolean_mask(mask_file)

    conditions = io.load_labels(epoch_file)