# Path: samri/utilities.py
# def collapse(img,
# 	min_dim=3,
# 	):
# 	"""
# 	Collapse a nibabel image allong its last axis
# 
# 	Parameters
# 	----------
# 	img : nibabel.nifti1.Nifti1Image
# 		Nibabel image to be collapsed.
# 	min_dim : int
# 		Bimensionality beyond which not to collapse.
# 	"""
# 
# 	ndim = 0
# 	data = img.get_data()
# 	for i in range(len(img.header['dim'])-1):
# 		current_dim = img.header['dim'][i+1]
# 		if current_dim == 1:
# 			break
# 		ndim += 1
# 	if ndim <= min_dim:
# 		return img
# 	img.header['dim'][0] = ndim
# 	img.header['pixdim'][ndim+1:] = 0
# 	data = np.mean(data,axis=(ndim-1))
# 	img = nib.nifti1.Nifti1Image(data, img.affine, img.header)
# 	return img
# 
# Path: samri/report/utilities.py
# def roi_data(img_path, masker,
# 	substitution={},
# 	exclude_zero=False,
# 	zero_threshold=0.1,
# 	):
# 	"""
# 	Return the mean of a Region of Interest (ROI) score.
# 
# 	Parameters
# 	----------
# 
# 	img_path : str
# 		Path to NIfTI file from which the ROI is to be extracted.
# 	makser : nilearn.NiftiMasker
# 		Nilearn `nifti1.Nifti1Image` object to use for masking the desired ROI.
# 	exclude_zero : bool, optional
# 		Whether to filter out zero values.
# 	substitution : dict, optional
# 		A dictionary with keys which include 'subject' and 'session'.
# 	zero_threshold : float, optional
# 		Absolute value below which values are to be considered zero.
# 	"""
# 	if substitution:
# 		img_path = img_path.format(**substitution)
# 	img_path = path.abspath(path.expanduser(img_path))
# 	img = nib.load(img_path)
# 	try:
# 		masked_data = masker.fit_transform(img)
# 	except:
# 		masker = path.abspath(path.expanduser(masker))
# 		masker = NiftiMasker(mask_img=masker)
# 		masked_data = masker.fit_transform(img)
# 	masked_data = masked_data.flatten()
# 	masked_data = masked_data[~np.isnan(masked_data)]
# 	if exclude_zero:
# 		masked_data = masked_data[np.abs(masked_data)>=zero_threshold]
# 	masked_mean = np.mean(masked_data)
# 	masked_median = np.median(masked_data)
# 	return masked_mean, masked_median


import nibabel as nib
import numpy as np
import pandas as pd
import scipy.stats as sps
import multiprocessing as mp
from os import path
from copy import deepcopy
from joblib import Parallel, delayed
from nilearn.input_data import NiftiMasker
from samri.utilities import collapse
from samri.report.utilities import roi_data
	save_as : str, optional
		Path to which to save the Pandas DataFrame.
	column_string : str, optional
		String to append after 'Mean' and 'Median' to construct the name of the mean and median columns.
	path_column : str, optional
		Column name which identifies the path of the data to analyze.
		zero_threshold : float, optional
		Absolute value below which values are to be considered zero.

	Returns
	-------

	pandas.DataFrame
		Pandas DataFrame object containing a row for each analyzed file and columns named 'Mean', 'Median', and (provided the respective key is present in the `sustitutions` variable) 'subject', 'session', 'task', and 'acquisition'.
	"""

	#Do not overwrite the input object
	df = deepcopy(df)

	in_files = df[path_column].tolist()
	iter_length = len(in_files)

	# Convert mask path to masker
	if isinstance(mask_path, str):
		mask_path = path.abspath(path.expanduser(mask_path))
	mask = NiftiMasker(mask_img=mask_path)

	# This is an easy jop CPU-wise, but not memory-wise.
	if not n_jobs:
		n_jobs = max(int(round(mp.cpu_count()*n_jobs_percentage)),2)

# Path: samri/utilities.py
# def collapse(img,
# 	min_dim=3,
# 	):
# 	"""
# 	Collapse a nibabel image allong its last axis
# 
# 	Parameters
# 	----------
# 	img : nibabel.nifti1.Nifti1Image
# 		Nibabel image to be collapsed.
# 	min_dim : int
# 		Bimensionality beyond which not to collapse.
# 	"""
# 
# 	ndim = 0
# 	data = img.get_data()
# 	for i in range(len(img.header['dim'])-1):
# 		current_dim = img.header['dim'][i+1]
# 		if current_dim == 1:
# 			break
# 		ndim += 1
# 	if ndim <= min_dim:
# 		return img
# 	img.header['dim'][0] = ndim
# 	img.header['pixdim'][ndim+1:] = 0
# 	data = np.mean(data,axis=(ndim-1))
# 	img = nib.nifti1.Nifti1Image(data, img.affine, img.header)
# 	return img
# 
# Path: samri/report/utilities.py
# def roi_data(img_path, masker,
# 	substitution={},
# 	exclude_zero=False,
# 	zero_threshold=0.1,
# 	):
# 	"""
# 	Return the mean of a Region of Interest (ROI) score.
# 
# 	Parameters
# 	----------
# 
# 	img_path : str
# 		Path to NIfTI file from which the ROI is to be extracted.
# 	makser : nilearn.NiftiMasker
# 		Nilearn `nifti1.Nifti1Image` object to use for masking the desired ROI.
# 	exclude_zero : bool, optional
# 		Whether to filter out zero values.
# 	substitution : dict, optional
# 		A dictionary with keys which include 'subject' and 'session'.
# 	zero_threshold : float, optional
# 		Absolute value below which values are to be considered zero.
# 	"""
# 	if substitution:
# 		img_path = img_path.format(**substitution)
# 	img_path = path.abspath(path.expanduser(img_path))
# 	img = nib.load(img_path)
# 	try:
# 		masked_data = masker.fit_transform(img)
# 	except:
# 		masker = path.abspath(path.expanduser(masker))
# 		masker = NiftiMasker(mask_img=masker)
# 		masked_data = masker.fit_transform(img)
# 	masked_data = masked_data.flatten()
# 	masked_data = masked_data[~np.isnan(masked_data)]
# 	if exclude_zero:
# 		masked_data = masked_data[np.abs(masked_data)>=zero_threshold]
# 	masked_mean = np.mean(masked_data)
# 	masked_median = np.median(masked_data)
# 	return masked_mean, masked_median


# Path: samri/report/snr.py
import nibabel as nib
import numpy as np
import pandas as pd
import scipy.stats as sps
import multiprocessing as mp
from os import path
from copy import deepcopy
from joblib import Parallel, delayed
from nilearn.input_data import NiftiMasker
from samri.utilities import collapse
from samri.report.utilities import roi_data

	save_as : str, optional
		Path to which to save the Pandas DataFrame.
	column_string : str, optional
		String to append after 'Mean' and 'Median' to construct the name of the mean and median columns.
	path_column : str, optional
		Column name which identifies the path of the data to analyze.
		zero_threshold : float, optional
		Absolute value below which values are to be considered zero.

	Returns
	-------

	pandas.DataFrame
		Pandas DataFrame object containing a row for each analyzed file and columns named 'Mean', 'Median', and (provided the respective key is present in the `sustitutions` variable) 'subject', 'session', 'task', and 'acquisition'.
	"""

	#Do not overwrite the input object
	df = deepcopy(df)

	in_files = df[path_column].tolist()
	iter_length = len(in_files)

	# Convert mask path to masker
	if isinstance(mask_path, str):
		mask_path = path.abspath(path.expanduser(mask_path))
	mask = NiftiMasker(mask_img=mask_path)

	# This is an easy jop CPU-wise, but not memory-wise.
	if not n_jobs:
		n_jobs = max(int(round(mp.cpu_count()*n_jobs_percentage)),2)

	iter_data = Parallel(n_jobs=n_jobs, verbose=0, backend="threading")(map(delayed(roi_data),