tfce_mediation/tm_func.py
def calculate_tfce(merge_y, masking_array, pred_x, calcTFCE, vdensity, position_array, fullmask, perm_number = None, randomise = False, verbose = False, no_intercept = True, set_surf_count = None, print_interation = False):
	X = np.column_stack([np.ones(merge_y.shape[0]),pred_x])
	if randomise:
		np.random.seed(perm_number+int(float(str(time())[-6:])*100))
		X = X[np.random.permutation(list(range(merge_y.shape[0])))]
	k = len(X.T)
	invXX = np.linalg.inv(np.dot(X.T, X))
	tvals = tval_int(X, invXX, merge_y, merge_y.shape[0], k, merge_y.shape[1])
	if no_intercept:
		tvals = tvals[1:,:]
	tvals = tvals.astype(np.float32, order = "C")
	tfce_tvals = np.zeros_like(tvals).astype(np.float32, order = "C")
	neg_tfce_tvals = np.zeros_like(tvals).astype(np.float32, order = "C")

	for tstat_counter in range(tvals.shape[0]):
		tval_temp = np.zeros_like((fullmask)).astype(np.float32, order = "C")
		if tvals.shape[0] == 1:
			tval_temp[fullmask==1] = tvals[0]
		else:
			tval_temp[fullmask==1] = tvals[tstat_counter]
		tval_temp = tval_temp.astype(np.float32, order = "C")
		tfce_temp = np.zeros_like(tval_temp).astype(np.float32, order = "C")
		neg_tfce_temp = np.zeros_like(tval_temp).astype(np.float32, order = "C")
		calcTFCE.run(tval_temp, tfce_temp)
		calcTFCE.run((tval_temp*-1), neg_tfce_temp)
		tval_temp = tval_temp[fullmask==1]
		tfce_temp = tfce_temp[fullmask==1]
		neg_tfce_temp = neg_tfce_temp[fullmask==1]
#		position = 0
		for surf_count in range(len(masking_array)):
			start = position_array[surf_count]
			end = position_array[surf_count+1]
			if isinstance(vdensity, int): # check vdensity is a scalar
				tfce_tvals[tstat_counter,start:end] = (tfce_temp[start:end] * (tval_temp[start:end].max()/100) * vdensity)
				neg_tfce_tvals[tstat_counter,start:end] = (neg_tfce_temp[start:end] * ((tval_temp*-1)[start:end].max()/100) * vdensity)
			else:
				tfce_tvals[tstat_counter,start:end] = (tfce_temp[start:end] * (tval_temp[start:end].max()/100) * vdensity[start:end])
				neg_tfce_tvals[tstat_counter,start:end] = (neg_tfce_temp[start:end] * ((tval_temp*-1)[start:end].max()/100) * vdensity[start:end])
			if randomise:
				if set_surf_count is not None:
					os.system("echo %f >> perm_maxTFCE_surf%d_tcon%d.csv" % (np.nanmax(tfce_tvals[tstat_counter,start:end]),int(set_surf_count[surf_count]),tstat_counter+1))
					os.system("echo %f >> perm_maxTFCE_surf%d_tcon%d.csv" % (np.nanmax(neg_tfce_tvals[tstat_counter,start:end]),int(set_surf_count[surf_count]),tstat_counter+1))
				else:
					os.system("echo %f >> perm_maxTFCE_surf%d_tcon%d.csv" % (np.nanmax(tfce_tvals[tstat_counter,start:end]),surf_count,tstat_counter+1))
					os.system("echo %f >> perm_maxTFCE_surf%d_tcon%d.csv" % (np.nanmax(neg_tfce_tvals[tstat_counter,start:end]),surf_count,tstat_counter+1))
			else:
				if set_surf_count is not None:
					print("Maximum (untransformed) postive tfce value for surface %s, tcon %d: %f" % (int(set_surf_count[surf_count]),tstat_counter+1,np.nanmax(tfce_tvals[tstat_counter,start:end]))) 
					print("Maximum (untransformed) negative tfce value for surface %s, tcon %d: %f" % (int(set_surf_count[surf_count]),tstat_counter+1,np.nanmax(neg_tfce_tvals[tstat_counter,start:end])))
				else:
					print("Maximum (untransformed) postive tfce value for surface %s, tcon %d: %f" % (surf_count,tstat_counter+1,np.nanmax(tfce_tvals[tstat_counter,start:end]))) 
					print("Maximum (untransformed) negative tfce value for surface %s, tcon %d: %f" % (surf_count,tstat_counter+1,np.nanmax(neg_tfce_tvals[tstat_counter,start:end])))
		if verbose:
			print("T-contrast: %d" % tstat_counter)
			print("Max tfce from all surfaces = %f" % tfce_tvals[tstat_counter].max())
			print("Max negative tfce from all surfaces = %f" % neg_tfce_tvals[tstat_counter].max())
	if randomise:
		if print_interation:
			print("Interation number: %d" % perm_number)
#		os.system("echo %s >> perm_maxTFCE_allsurf.csv" % ( ','.join(["%0.2f" % i for i in tfce_tvals.max(axis=1)] )) )
#		os.system("echo %s >> perm_maxTFCE_allsurf.csv" % ( ','.join(["%0.2f" % i for i in neg_tfce_tvals.max(axis=1)] )) )
		tvals = None
		tfce_tvals = None
		neg_tfce_tvals = None
	tval_temp = None
	tfce_temp = None
	neg_tfce_temp = None
	del calcTFCE
	if not randomise:
		return (tvals.astype(np.float32, order = "C"), tfce_tvals.astype(np.float32, order = "C"), neg_tfce_tvals.astype(np.float32, order = "C"))
tfce_mediation/tm_func.py
def paint_surface(lowthresh, highthres, color_scheme, data_array, save_colorbar = True):
	colormaps = np.array(plt.colormaps(),dtype=np.str)
	if (str(color_scheme) == 'r_y') or (str(color_scheme) == 'red-yellow'):
		out_color_array = convert_redtoyellow(np.array((float(lowthresh),float(highthres))), data_array, save_colorbar = save_colorbar)
	elif (str(color_scheme) == 'b_lb') or (str(color_scheme) == 'blue-lightblue'):
		out_color_array = convert_bluetolightblue(np.array((float(lowthresh),float(highthres))), data_array, save_colorbar = save_colorbar)
	elif np.any(colormaps == str(color_scheme)):
		out_color_array = convert_mpl_colormaps(np.array((float(lowthresh),float(highthres))), data_array, str(color_scheme), save_colorbar = save_colorbar)
	else:
		print("Error: colour scheme %s does not exist" % str(color_scheme))
		quit()
	return out_color_array
tfce_mediation/tm_func.py
def apply_mfwer(image_array, num_contrasts, surface_range, num_perm, num_surf, tminame, position_array, pos_range, neg_range = None, method = 'scale', weight = None, mediation = False, medtype = None): 
	# weight = None is essentially Tippet without considering mask size

	maxvalue_array = np.zeros((num_perm,num_contrasts))
	temp_max = np.zeros((num_perm, num_surf))
	positive_data = np.zeros((image_array[0].shape[0],num_contrasts))
	if mediation == False:
		negative_data = np.zeros((image_array[0].shape[0],num_contrasts))

	if weight == 'logmasksize':
		x = []
		for i in range(len(position_array)-1):
			x.append((position_array[i+1] - position_array[i]))
		weights = (np.log(x)/np.log(x).sum())/np.mean(np.log(x)/np.log(x).sum()) # weights between mask size and max values probablity.
		w_temp_max = np.zeros((num_perm, num_surf))

	for contrast in range(num_contrasts):
		for surface in surface_range: # the standardization is done within each surface
			if mediation == False:
				log_perm_results = np.log(np.genfromtxt('output_%s/perm_maxTFCE_surf%d_tcon%d.csv' % (tminame,surface,contrast+1))[:num_perm])
			else:
				log_perm_results = np.log(np.genfromtxt('output_%s/perm_maxTFCE_surf%d_%s_zstat.csv' % (tminame,surface,str(medtype)))[:num_perm])
			# set log(0) back to zero (only happens with small masks and very large effect sizes)
			log_perm_results[np.isinf(log_perm_results)] = 0
			start = position_array[surface]
			end = position_array[surface+1]

			# log transform, standarization
			posvmask = np.log(image_array[0][start:end,pos_range[contrast]]) > 0
			temp_lt = np.log(image_array[0][start:end,pos_range[contrast]][posvmask]) # log and z transform the images by the permutation values (the max tfce values are left skewed)
			temp_lt -= log_perm_results.mean()
			temp_lt /= log_perm_results.std()
			temp_lt += 10
			positive_data[start:end,contrast][posvmask] = temp_lt
			del temp_lt, posvmask

			if mediation == False:
				posvmask = np.log(image_array[0][start:end,neg_range[contrast]]) > 0
				temp_lt = np.log(image_array[0][start:end,neg_range[contrast]][posvmask]) # log and z transform the images by the permutation values (the max tfce values are left skewed)
				temp_lt -= log_perm_results.mean()
				temp_lt /= log_perm_results.std()
				temp_lt += 10
				negative_data[start:end,contrast][posvmask] = temp_lt
				del temp_lt, posvmask

			log_perm_results -= log_perm_results.mean() # standardize the max TFCE values 
			log_perm_results /= log_perm_results.std()
			if weight == 'logmasksize':
				w_log_perm_results = log_perm_results * weights[surface]
				w_log_perm_results += 10
				w_temp_max[:,surface] = w_log_perm_results
			log_perm_results += 10
			temp_max[:,surface] = log_perm_results


		if not weight == None:
			w_temp_max[np.isnan(w_temp_max)]=0
			max_index = np.argmax(w_temp_max, axis=1)
			max_value_list = np.zeros((len(max_index)),dtype=np.float32) # this should not be necessary
			for i in range(len(temp_max)):
				max_value_list[i]= temp_max[i,max_index[i]]
			maxvalue_array[:,contrast] = np.sort(max_value_list)
			del max_value_list
		else:
			maxvalue_array[:,contrast] = np.sort(temp_max.max(axis=1))
	del temp_max
	# two for loops just so my brain doesn't explode
	for contrast in range(num_contrasts):
		sorted_perm_tfce_max=maxvalue_array[:,contrast]
		p_array=np.zeros_like(sorted_perm_tfce_max)
		corrp_img = np.zeros((positive_data.shape[0]))
		for j in range(num_perm):
			p_array[j] = np.true_divide(j,num_perm)
		cV=0
		for k in positive_data[:,contrast]:
			corrp_img[cV] = find_nearest(sorted_perm_tfce_max,k,p_array)
			cV+=1
		positive_data[:,contrast] = np.copy(corrp_img)
		if mediation == False:
			cV=0
			corrp_img = np.zeros((negative_data.shape[0]))
			for k in negative_data[:,contrast]:
				corrp_img[cV] = find_nearest(sorted_perm_tfce_max,k,p_array)
				cV+=1
			negative_data[:,contrast] = np.copy(corrp_img)
	if mediation == False:
		return positive_data, negative_data
	else:
		return positive_data
tfce_mediation/tm_io.py
def savenifti_v2(image_array, index, imagename, affine=None):
	if not ((imagename.endswith('nii')) or (imagename.endswith('nii.gz'))):
		imagename += '.nii.gz'
	outdata = image_array.astype(np.float32, order = "C")
	if image_array.ndim == 2:
		imgout = np.zeros((index.shape[0],index.shape[1],index.shape[2],image_array.shape[1]))
	elif image_array.ndim == 1:
		imgout = np.zeros((index.shape[0],index.shape[1],index.shape[2]))
	else:
		print('error')
	imgout[index]=outdata
	nib.save(nib.Nifti1Image(imgout.astype(np.float32, order = "C"),affine=affine),imagename)
tfce_mediation/tm_func.py
def create_position_array(masking_array):
	pointer = 0
	position_array = [0]
	for i in range(len(masking_array)):
		pointer += len(masking_array[i][masking_array[i]==True])
		position_array.append(pointer)
	return position_array
tfce_mediation/tm_func.py
def calculate_mediation_tfce(medtype, merge_y, masking_array, pred_x, depend_y, calcTFCE, vdensity, position_array, fullmask, perm_number = None, randomise = False, verbose = False, no_intercept = True, print_interation = False):
	if randomise:
		np.random.seed(perm_number+int(float(str(time())[-6:])*100))
		indices_perm = np.random.permutation(list(range(merge_y.shape[0])))
		if (medtype == 'M') or (medtype == 'I'):
			if randomise:
				pred_x = pred_x[indices_perm]
		else:
			if randomise:
				pred_x = pred_x[indices_perm]
				depend_y = depend_y[indices_perm]
	SobelZ = calc_sobelz(medtype, pred_x, depend_y, merge_y, merge_y.shape[0], merge_y.shape[1])
	SobelZ = SobelZ.astype(np.float32, order = "C")
	tfce_SobelZ = np.zeros_like(SobelZ).astype(np.float32, order = "C")
	zval_temp = np.zeros_like((fullmask)).astype(np.float32, order = "C")
	zval_temp[fullmask==1] = SobelZ
	zval_temp = zval_temp.astype(np.float32, order = "C")
	tfce_temp = np.zeros_like(zval_temp).astype(np.float32, order = "C")
	calcTFCE.run(zval_temp, tfce_temp)
	zval_temp = zval_temp[fullmask==1]
	tfce_temp = tfce_temp[fullmask==1]
	for surf_count in range(len(masking_array)):
		start = position_array[surf_count]
		end = position_array[surf_count+1]
		if isinstance(vdensity, int): # check vdensity is a scalar
			tfce_SobelZ[start:end] = (tfce_temp[start:end] * (zval_temp[start:end].max()/100) * vdensity)
		else:
			tfce_SobelZ[start:end] = (tfce_temp[start:end] * (zval_temp[start:end].max()/100) * vdensity[start:end])
		if randomise:
			os.system("echo %f >> perm_maxTFCE_surf%d_%s_zstat.csv" % (np.nanmax(tfce_SobelZ[start:end]), surf_count, medtype))
		else:
			print("Max Sobel Z tfce value for surface %s:\t %1.5f" % (surf_count, np.nanmax(tfce_SobelZ[start:end]))) 
	if verbose:
		print("Max Zstat tfce from all surfaces = %f" % tfce_SobelZ.max())
	if randomise:
		print("Interation number: %d" % perm_number)
		SobelZ = None
		tfce_SobelZ = None
	zval_temp = None
	tfce_temp = None
	del calcTFCE
	if not randomise:
		return (SobelZ.astype(np.float32, order = "C"), tfce_SobelZ.astype(np.float32, order = "C"))
tfce_mediation/tm_func.py
def create_full_mask(masking_array):
	# make mega mask
	fullmask = []
	for i in range(len(masking_array)):
		if masking_array[i].shape[2] == 1: # check if vertex or voxel image
			fullmask = np.hstack((fullmask, masking_array[i][:,0,0]))
		else:
			fullmask = np.hstack((fullmask, masking_array[i][masking_array[i]==True]))
	return fullmask
tfce_mediation/pyfunc.py
def save_ply(v, f, outname, color_array=None, output_binary=True):
	# check file extension
	if not outname.endswith('ply'):
		if output_binary:
			outname += '.ply'
		else:
			outname += '.ascii.ply'
	outname=check_outname(outname)

	# write header 
	header = ("ply\n")
	if output_binary:
		header += ("format binary_%s_endian 1.0\n" % (sys.byteorder))
		if sys.byteorder == 'little':
			output_fmt = '<'
		else:
			output_fmt = '>'
	else:
		header += ("format ascii 1.0\n")
	header += ("comment made with TFCE_mediation\n")
	header += ("element vertex %d\n" % len(v))
	header += ("property float x\n")
	header += ("property float y\n")
	header += ("property float z\n")
	if color_array is not None:
		header += ("property uchar red\n")
		header += ("property uchar green\n")
		header += ("property uchar blue\n")
	header += ("element face %d\n" % len(f))
	header += ("property list uchar int vertex_index\n")
	header += ("end_header\n")

	# write to file
	with open(outname, "a") as o:
		o.write(header)
		for i in range(len(v)):
			if output_binary:
				if color_array is not None:
					o.write(
						struct.pack(output_fmt + 'fffBBB', v[i, 0], v[i, 1], v[i, 2], color_array[i, 0], color_array[i, 1], color_array[i, 2]))
				else:
					o.write(struct.pack(output_fmt + 'fff', v[i, 0], v[i, 1], v[i, 2]))
			else:
				if color_array is not None:
					o.write("%1.6f %1.6f %1.6f %d %d %d\n" % (v[i, 0], v[i, 1], v[i, 2], color_array[i, 0], color_array[i, 1], color_array[i, 2]))
				else:
					o.write("%1.6f %1.6f %1.6f\n" % (v[i, 0], v[i, 1], v[i, 2]))
		for j in range(len(f)):
			if output_binary:
				o.write(struct.pack('<Biii', 3, f[j, 0], f[j, 1], f[j, 2]))
			else:
				o.write("3 %d %d %d\n" % (f[j, 0], f[j, 1], f[j, 2]))
tfce_mediation/tm_func.py
def calc_mixed_tfce(assigntfcesettings, merge_y, masking_array, position_array, vdensity, pred_x, calcTFCE, perm_number = None, randomise = False, medtype = None, depend_y = None):
	for i in np.unique(assigntfcesettings):
		data_mask = np.zeros(merge_y.shape[1], dtype=bool)
		extract_range = np.argwhere(assigntfcesettings==i)
		for surface in extract_range:
			start = position_array[int(surface)]
			end = position_array[int(surface)+1]
			data_mask[start:end] = True
		subset_merge_y = merge_y[:,data_mask]
		try:
			temp_vdensity = vdensity[data_mask]
		except:
			temp_vdensity = 1

		if randomise:
			
			if i == 0:
				display_iter = True
			else:
				display_iter = False

			calculate_tfce(subset_merge_y, 
				np.array(masking_array)[assigntfcesettings==i], 
				pred_x, 
				calcTFCE[i], 
				temp_vdensity, 
				create_position_array(np.array(masking_array)[assigntfcesettings==i]),
				create_full_mask(np.array(masking_array)[assigntfcesettings==i]),
				set_surf_count = extract_range,
				perm_number=perm_number, 
				randomise = True,
				print_interation = display_iter)
		else:
			temp_tvals, temp_tfce_tvals, temp_neg_tfce_tvals = calculate_tfce(subset_merge_y, 
				np.array(masking_array)[assigntfcesettings==i], 
				pred_x, 
				calcTFCE[i], 
				temp_vdensity, 
				create_position_array(np.array(masking_array)[assigntfcesettings==i]),
				create_full_mask(np.array(masking_array)[assigntfcesettings==i]),
				set_surf_count = extract_range)

			if i == 0: # at first instance
				tvals = tfce_tvals = neg_tfce_tvals = np.zeros((temp_tvals.shape[0],merge_y.shape[1]))
			tvals[:,data_mask] = temp_tvals
			tfce_tvals[:,data_mask] = temp_tfce_tvals
			neg_tfce_tvals[:,data_mask] = temp_neg_tfce_tvals
			temp_tvals = None
			temp_tfce_tvals = None
			temp_neg_tfce_tvals = None
	if not randomise:
		return tvals, tfce_tvals, neg_tfce_tvals
tfce_mediation/pyfunc.py
def vectorized_surface_smooth(v, f, adjacency, number_of_iter = 5, scalar = None, lambda_w = 0.5, mode = 'laplacian', weighted = True):
	"""
	Applies Laplacian (Gaussian) or Taubin (low-pass) smoothing with option to smooth single volume
	
	Citations
	----------
	
	Herrmann, Leonard R. (1976), "Laplacian-isoparametric grid generation scheme", Journal of the Engineering Mechanics Division, 102 (5): 749-756.
	Taubin, Gabriel. "A signal processing approach to fair surface design." Proceedings of the 22nd annual conference on Computer graphics and interactive techniques. ACM, 1995.
	
	
	Parameters
	----------
	v : array
		vertex array
	f : array
		face array
	adjacency : array
		adjacency array

	
	Flags
	----------
	number_of_iter : int
		number of smoothing iterations
	scalar : array
		apply the same smoothing to a image scalar
	lambda_w : float
		lamda weighting of degree of movement for each iteration
		The weighting should never be above 1.0
	mode : string
		The type of smoothing can either be laplacian (which cause surface shrinkage) or taubin (no shrinkage)
		
	Returns
	-------
	v_smooth : array
		smoothed vertices array
	f : array
		f = face array (unchanged)
	
	Optional returns
	-------
	values : array
		smoothed scalar array
	
	"""
	k = 0.1
	mu_w = -lambda_w/(1-k*lambda_w)

	lengths = np.array([len(a) for a in adjacency])
	maxlen = max(lengths)
	padded = [list(a) + [-1] * (maxlen - len(a)) for a in adjacency]
	adj = np.array(padded)
	w = np.ones(adj.shape, dtype=float)
	w[adj<0] = 0.
	val = (adj>=0).sum(-1).reshape(-1, 1)
	w /= val
	w = w.reshape(adj.shape[0], adj.shape[1],1)

	vorig = np.zeros_like(v)
	vorig[:] = v
	if scalar is not None:
		scalar[np.isnan(scalar)] = 0
		sorig = np.zeros_like(scalar)
		sorig[:] = scalar

	for iter_num in range(number_of_iter):
		if weighted:
			vadj = v[adj]
			vadj = np.swapaxes(v[adj],1,2)
			weights = np.zeros((v.shape[0], maxlen))
			for col in range(maxlen):
				weights[:,col] = np.power(np.linalg.norm(vadj[:,:,col] - v, axis=1),-1)
			weights[adj==-1] = 0
			vectors = np.einsum('abc,adc->acd', weights[:,None], vadj)

			if scalar is not None:
				scalar[np.isnan(scalar)] = 0

				sadj = scalar[adj]
				sadj[adj==-1] = 0
				if lambda_w < 1:
					scalar = (scalar*(1-lambda_w)) + lambda_w*(np.sum(np.multiply(weights, sadj),axis=1) / np.sum(weights, axis = 1))
				else:
					scalar = np.sum(np.multiply(weights, sadj),axis=1) / np.sum(weights, axis = 1)
				scalar[np.isnan(scalar)] = sorig[np.isnan(scalar)] # hacky scalar nan fix
			if iter_num % 2 == 0:
				v += lambda_w*(np.divide(np.sum(vectors, axis = 1), np.sum(weights[:,None], axis = 2)) - v)
			elif mode == 'taubin':
				v += mu_w*(np.divide(np.sum(vectors, axis = 1), np.sum(weights[:,None], axis = 2)) - v)
			elif mode == 'laplacian':
				v += lambda_w*(np.divide(np.sum(vectors, axis = 1), np.sum(weights[:,None], axis = 2)) - v)
			else:
				print("Error: mode %s not understood" % mode)
				quit()
			v[np.isnan(v)] = vorig[np.isnan(v)] # hacky vertex nan fix
		else:
			if scalar is not None:
				sadj = scalar[adj]
				sadj[adj==-1] = 0

				if lambda_w < 1:
					scalar = (scalar*(1-lambda_w)) + (lambda_w*np.divide(np.sum(sadj, axis = 1),lengths))
				else:
					scalar = np.divide(np.sum(sadj, axis = 1),lengths)
			if iter_num % 2 == 0:
				v += np.array(lambda_w*np.swapaxes(w,0,1)*(np.swapaxes(v[adj], 0, 1)-v)).sum(0)
			elif mode == 'taubin':
				v += np.array(mu_w*np.swapaxes(w,0,1)*(np.swapaxes(v[adj], 0, 1)-v)).sum(0)
			elif mode == 'laplacian':
				v += np.array(lambda_w*np.swapaxes(w,0,1)*(np.swapaxes(v[adj], 0, 1)-v)).sum(0)
			else:
				print("Error: mode %s not understood" % mode)
				quit()

	if scalar is not None:
		return (v, f, scalar)
	else:
		return (v, f)
tfce_mediation/tm_io.py
def write_tm_filetype(outname, columnids = [], imgtype = [], checkname = True, output_binary = True, image_array = [], masking_array = [], maskname = [],  affine_array = [], vertex_array = [], face_array = [], surfname = [], adjacency_array = [], tmi_history = [], append_history = True): # NOTE: add ability to store subjectids and imgtypes
	# timestamp
	currentTime=int(strftime("%Y%m%d%H%M%S",gmtime()))
	# counters
	num_data = 0
	num_mask = 0
	num_object = 0
	num_affine = 0
	num_adjacency = 0
	# history counters
	h_mask = 0
	h_affine = 0
	h_object = 0
	h_adjacency = 0

	if not tmi_history == []:
		for i in range(len(tmi_history)):
			line = tmi_history[i].split(' ')
			if line[1] == 'mode_add':
				h_mask += int(line[4])
				h_affine += int(line[5])
				h_object += int(line[6])
				h_adjacency += int(line[7])
			elif line[1] == 'mode_sub':
				h_mask -= int(line[4])
				h_affine -= int(line[5])
				h_object -= int(line[6])
				h_adjacency -= int(line[7])
			elif line[1] == 'mode_replace':
				pass
			elif line[1] == 'mode_reorder':
				pass
			else:
				print(("Error reading history. Mode %s is not understood. Count is reflect number of element in current file" % line[1]))

	if not masking_array == []:
		masking_array=np.array(masking_array)
		if (masking_array.dtype.kind=='O') or (masking_array.ndim==4):
			num_mask=int(masking_array.shape[0])
		elif masking_array.ndim==3:
			num_mask = 1
		else:
			print("Error mask dimension are not understood")
	if not vertex_array==[]:
		vertex_array=np.array(vertex_array)
		if vertex_array.ndim==2:
			num_object = 1
		elif (vertex_array.dtype.kind == 'O') or (vertex_array.ndim==3):
			num_object=int(vertex_array.shape[0])
		else:
			print("Error surface object dimension are not understood.")
	if not affine_array==[]:
		affine_array=np.array(affine_array)
		if affine_array.ndim==2:
			num_affine = 1
		elif (affine_array.dtype.kind == 'O') or (affine_array.ndim==3):
			num_affine=int(affine_array.shape[0])
		else:
			print("Error affine dimension are not understood.")
	if not adjacency_array==[]:
		adjacency_array=np.array(adjacency_array)
		if (adjacency_array.dtype.kind == 'O') or (adjacency_array.ndim==2):
			num_adjacency=int(adjacency_array.shape[0])
		elif adjacency_array.ndim==1:
			num_adjacency = 1
		else:
			print("Error shape of adjacency objects are not understood.")

	# write array shape
	if not image_array == []:
		num_data = 1
		if image_array.ndim == 1:
			nvert=len(image_array)
			nsub = 1
		else:
			nvert=image_array.shape[0]
			nsub=image_array.shape[1]
	if not outname.endswith('tmi'):
		if output_binary:
			if not outname.endswith('tmi'):
				outname += '.tmi'
		else:
			outname += '.ascii.tmi'
	if checkname:
		outname=check_outname(outname)
	with open(outname, "w") as o:
		o.write("tmi\n")
		if output_binary:
			o.write("format binary_%s_endian %s\n" % ( sys.byteorder, tm_filetype_version() ) )
		else:
			o.write("format ascii %s\n" % tm_filetype_version() )
		o.write("comment made with TFCE_mediation\n")
		if not image_array==[]:
			o.write("element data_array\n")
			o.write("dtype float32\n")
			o.write("nbytes %d\n" % image_array.astype('float32').nbytes)
			o.write("datashape %d %d\n" % (nvert,nsub))

		if num_mask>0:
			for i in range(num_mask):
				o.write("element masking_array\n")
				o.write("dtype uint8\n") # for binarized masks
				o.write("nbytes %d\n" % masking_array[i].nbytes)
				o.write("nmasked %d\n" % len(masking_array[i][masking_array[i]==True]))
				o.write("maskshape %d %d %d\n" % (masking_array[i].shape[0],masking_array[i].shape[1],masking_array[i].shape[2]))
				if maskname is not []:
					o.write("maskname %s\n" % maskname[i])
				else:
					o.write("maskname unknown\n")

		if num_affine>0:
			for i in range(num_affine):
				o.write("element affine\n")
				o.write("dtype float32\n")
				o.write("nbytes %d\n" % affine_array[i].astype('float32').nbytes)
				o.write("affineshape %d %d\n" % (affine_array[i].shape[0], affine_array[i].shape[1]) )

		if num_object>0:
			for i in range(num_object):
				if surfname is not []:
					o.write("surfname %s\n" % surfname[i])
				else:
					o.write("surfname unknown\n")

				o.write("element vertex\n")
				o.write("dtype float32\n")
				o.write("nbytes %d\n" % vertex_array[i].astype('float32').nbytes)
				o.write("vertexshape %d %d\n" % (vertex_array[i].shape[0], vertex_array[i].shape[1]) )

				o.write("element face\n")
				o.write("dtype uint32\n")
				o.write("nbytes %d\n" % face_array[i].astype('uint32').nbytes)
				o.write("faceshape %d %d\n" % (face_array[i].shape[0], face_array[i].shape[1]))

		if num_adjacency>0:
			for i in range(num_adjacency):
				o.write("element adjacency_object\n")
				o.write("dtype python_object\n")
				o.write("nbytes %d\n" % len(pickle.dumps(adjacency_array[i], -1)) )
				o.write("adjlength %d\n" % len(adjacency_array[i]) )

		if not np.array_equal(columnids, []):
				o.write("element column_id\n")
				o.write("dtype %s\n" % columnids.dtype)
				o.write("nbytes %d\n" % columnids.nbytes)
				o.write("listlength %d\n" % len(columnids))

		# create a recorded of what was added to the file. 'mode_add' denotes these items were added. tmi_history is expandable.
		if append_history:
			tmi_history.append("history mode_add %d %d %d %d %d %d" % (currentTime, num_data, num_mask-h_mask, num_affine-h_affine, num_object-h_object, num_adjacency-h_adjacency) )
		for i in range(len(tmi_history)):
			o.write('%s\n' % (tmi_history[i]) )
		o.write("end_header\n")
		o.close()

		if output_binary:
			with open(outname, "ab") as o:
				image_array = np.array(image_array.T, dtype='float32') # transpose to reduce file size
				image_array.tofile(o)
				if num_mask>0:
					for j in range(num_mask):
						binarymask = masking_array[j] * 1
						binarymask = np.array(binarymask.T, dtype=np.uint8)
						binarymask.tofile(o)
				if num_affine>0:
					for j in range(num_affine):
						outaffine = np.array(affine_array[j].T, dtype='float32')
						outaffine.tofile(o)
				if num_object>0:
					for j in range(num_object):
						outv = np.array(vertex_array[j].T, dtype='float32')
						outv.tofile(o)
						outf = np.array(face_array[j].T, dtype='uint32')
						outf.tofile(o)
				if not np.array_equal(columnids, []):
					columnids.tofile(o)
				if num_adjacency>0:
					for j in range(num_adjacency):
						pickle.dump(adjacency_array[j],o, protocol=pickle.HIGHEST_PROTOCOL)
		else:
			with open(outname, "a") as o:
				if not image_array == []:
					np.savetxt(o,image_array.astype(np.float32))
				if num_mask>0:
					for j in range(num_mask):
						binarymask = masking_array[j] * 1
						binarymask = np.array(binarymask, dtype=np.uint8)
						x, y, z = np.ma.nonzero(binarymask)
						for i in range(len(x)):
							o.write("%d %d %d\n" % (int(x[i]), int(y[i]), int(z[i]) ) )
				if num_affine>0:
					for j in range(num_affine):
						outaffine = np.array(affine_array[j])
						np.savetxt(o,outaffine.astype(np.float32))
				if columnids is not []:
					columnids.tofile(o, sep='\n', format="%s")
				if num_object>0:
					for k in range(num_object):
						for i in range(len(vertex_array[k])):
							o.write("%1.6f %1.6f %1.6f\n" % (vertex_array[k][i,0],
								vertex_array[k][i,1],
								vertex_array[k][i,2]))
						for j in range(len(face_array[k])):
							o.write("%d %d %d\n" % (int(face_array[k][j,0]),
								int(face_array[k][j,1]),
								int(face_array[k][j,2])))
		o.close()
tfce_mediation/tm_io.py
def read_tm_filetype(tm_file, verbose=True):
	# getfilesize
	filesize = os.stat(tm_file).st_size
	# declare variables
	element = []
	element_dtype = []
	element_nbyte = []
	element_nmasked = []
	masking_array = []
	datashape = []
	maskshape = []
	maskname = []
	vertexshape = []
	faceshape = []
	surfname = []
	affineshape = []
	adjlength = []
	array_read = []
	object_read = []
	o_imgarray = []
	o_masking_array = []
	o_vertex = []
	o_face = []
	o_affine = []
	o_adjacency = []
	o_columnids = []
	maskcounter = 0
	vertexcounter = 0
	facecounter = 0
	affinecounter = 0
	adjacencycounter = 0
	tmi_history = []

	# read first line
	obj = open(tm_file, 'rb')
	reader = obj.readline().decode("UTF-8").strip().split()
	firstword=reader[0]
	if firstword != 'tmi':
		print("Error: not a TFCE_mediation image.")
		exit()
	reader = obj.readline().decode("UTF-8").strip().split()
	firstword=reader[0]
	if firstword != 'format':
		print("Error: unknown reading file format")
		exit()
	else:
		tm_filetype = reader[1]


	while firstword != 'end_header':
		reader = obj.readline().decode("UTF-8").strip().split()
		firstword=reader[0]
		if firstword == 'element':
			element.append((reader[1]))
		if firstword == 'dtype':
			element_dtype.append((reader[1]))
		if firstword == 'nbytes':
			element_nbyte.append((reader[1]))
		if firstword == 'datashape':
			datashape.append(np.array((reader[1], reader[2])).astype(np.int))
		if firstword == 'nmasked':
			element_nmasked.append(( int(reader[1]) ))
		if firstword == 'maskshape':
			maskshape.append(np.array((reader[1], reader[2], reader[3])).astype(np.int))
		if firstword == 'maskname':
			maskname.append((reader[1]))
		if firstword == 'affineshape':
			affineshape.append(np.array((reader[1], reader[2])).astype(np.int))
		if firstword == 'vertexshape':
			vertexshape.append(np.array((reader[1], reader[2])).astype(np.int))
		if firstword == 'surfname':
			surfname.append((reader[1]))
		if firstword == 'faceshape':
			faceshape.append(np.array((reader[1], reader[2])).astype(np.int))
		if firstword == 'adjlength':
			adjlength.append(np.array(reader[1]).astype(np.int))
		if firstword == 'history':
			tmi_history.append(str(' '.join(reader)))
		if firstword == 'listlength':
			listlength=int(reader[1])
	# skip header
	position = filesize
	for i in range(len(element_nbyte)):
		position-=int(element_nbyte[i])
	# readdata
	if tm_filetype == 'binary_little_endian':
		for e in range(len(element)):
			obj.seek(position)
			if verbose:
				print(position)
				print("reading %s" % str(element[e]))
			if not str(element[e]) == 'adjacency_object':
				array_read = np.fromfile(obj, dtype=element_dtype[e])
			else:
				object_read.append(pickle.load(obj))
			position += int(element_nbyte[e])
			# reshape arrays
			if str(element[e]) == 'data_array':
				o_imgarray.append(np.array(array_read[:datashape[0][0]*datashape[0][1]]).reshape(datashape[0][1],datashape[0][0]).T)
			if str(element[e]) == 'masking_array':
				masktemp = np.array(array_read[:(maskshape[maskcounter][2]*maskshape[maskcounter][1]*maskshape[maskcounter][0])]).reshape(maskshape[maskcounter][2],maskshape[maskcounter][1],maskshape[maskcounter][0]).T
				o_masking_array.append((np.array(masktemp, dtype=bool) ))
				maskcounter += 1
			if str(element[e]) == 'affine':
				o_affine.append(np.array(array_read[:affineshape[affinecounter][1]*affineshape[affinecounter][0]]).reshape(affineshape[affinecounter][1],affineshape[affinecounter][0]).T)
				affinecounter += 1
			if str(element[e]) == 'vertex':
				o_vertex.append(np.array(array_read[:vertexshape[vertexcounter][1]*vertexshape[vertexcounter][0]]).reshape(vertexshape[vertexcounter][1],vertexshape[vertexcounter][0]).T)
				vertexcounter += 1
			if str(element[e]) == 'face':
				o_face.append(np.array(array_read[:faceshape[facecounter][1]*faceshape[facecounter][0]]).reshape(faceshape[facecounter][1],faceshape[facecounter][0]).T)
				facecounter += 1
			if str(element[e]) == 'column_id':
				o_columnids.append(np.array(array_read[:listlength]))
			if str(element[e]) == 'adjacency_object':
				o_adjacency.append(np.array(object_read[adjacencycounter][:adjlength[adjacencycounter]]))
				adjacencycounter += 1
			array_read = []
	elif tm_filetype == 'ascii':
		for e in range(len(element)):
			if str(element[e]) == 'data_array':
				img_data = np.zeros((datashape[0][0], datashape[0][1]))
				for i in range(int(datashape[0][0])):
					img_data[i] = np.array(obj.readline().strip().split(), dtype = 'float32')
				o_imgarray.append((np.array(img_data, dtype = 'float32')))
			if str(element[e]) == 'masking_array':
					for k in range(element_nmasked[maskcounter]):
						masking_array.append((np.array(obj.readline().strip().split()).astype(np.int32)))
					masking_array = np.array(masking_array)
					outmask = np.zeros((maskshape[maskcounter]), dtype=np.int)
					outmask[masking_array[:,0],masking_array[:,1],masking_array[:,2]] = 1
					o_masking_array.append((np.array(outmask, dtype=bool)))
					maskcounter += 1
					masking_array=[]
			if str(element[e]) == 'affine':
				temparray = []
				for k in range(int(affineshape[affinecounter][0])):
					temparray.append((np.array(obj.readline().strip().split()).astype('float32')))
				o_affine.append((np.array(temparray, dtype='float32')))
				affinecounter += 1
			if str(element[e]) == 'vertex':
				temparray = []
				for k in range(int(vertexshape[vertexcounter][0])):
					temparray.append((np.array(obj.readline().strip().split()).astype('float32')))
				o_vertex.append((np.array(temparray, dtype='float32')))
				vertexcounter += 1
			if str(element[e]) == 'face':
				temparray = []
				for k in range(int(faceshape[facecounter][0])):
					temparray.append((np.array(obj.readline().strip().split()).astype('int32')))
				o_face.append(( np.array(temparray, dtype='int32') ))
				facecounter += 1
			if str(element[e]) == 'column_id':
				temparray = []
				for k in range(listlength):
					temparray.append(obj.readline().strip() )
				o_columnids.append(( np.array(temparray, dtype=element_dtype[e]) ))

	else:
		print("Error unknown filetype: %s" % tm_filetype)
	return(element, o_imgarray, o_masking_array, maskname, o_affine, o_vertex, o_face, surfname, o_adjacency, tmi_history, o_columnids)
tfce_mediation/tm_io.py
def savemgh_v2(image_array, index, imagename, affine=None):
	if not imagename.endswith('mgh'):
		imagename += '.mgh'
	outdata = image_array.astype(np.float32, order = "C")
	if image_array.ndim == 1:
		imgout = np.zeros((index.shape[0],index.shape[1],index.shape[2]))
		imgout[index]=outdata
	elif image_array.shape[1] > 1:
		imgout = np.zeros((index.shape[0],index.shape[1],index.shape[2],image_array.shape[1]))
		imgout[index]=outdata
	else:
		imgout = np.zeros((index.shape[0],index.shape[1],index.shape[2]))
		imgout[index]=outdata[:,0]
	nib.save(nib.freesurfer.mghformat.MGHImage(imgout.astype(np.float32, order = "C"),affine=affine),imagename)
tfce_mediation/pyfunc.py
def convert_voxel(img_data, affine = None, threshold = None, data_mask = None, absthreshold = None):
	"""
	Converts a voxel image to a surface including outputs voxel values to paint vertex surface.
	
	Parameters
	----------
	img_data : array
		image array
	affine : array
		 affine [4x4] to convert vertices values to native space (Default = None)
	data_mask : array
		use a mask to create a surface backbone (Default = None)
	threshold : float
		threshold for output of voxels (Default = None)
	absthreshold : float
		threshold for output of abs(voxels) (Default = None)
		
	Returns
	-------
		v : array
			vertices
		f : array
			faces
		values : array
			scalar values
	
	"""
	try:
		from skimage import measure
	except:
		print("Error skimage is required")
		quit()

	if threshold is not None:
		print("Zeroing data less than threshold = %1.2f" % threshold)
		img_data[img_data<threshold] = 0
	if absthreshold is not None:
		print("Zeroing absolute values less than threshold = %1.2f" % absthreshold)
		img_data[np.abs(img_data)<absthreshold] = 0
	if data_mask is not None:
		print("Including mask")
		data_mask *= .1
		data_mask[img_data!=0] = img_data[img_data!=0]
		del img_data
		img_data = np.copy(data_mask)
	try:
		v, f, _, values = measure.marching_cubes_lewiner(img_data)
		if affine is not None:
			print("Applying affine transformation")
			v = nib.affines.apply_affine(affine,v)
	except:
		print("No voxels above threshold")
		v = f = values = []
	return v, f, values
tfce_mediation/tm_func.py
def saveauto(image_array, index, imagename, affine=None):
	if index.shape[2] > 1:
		savenifti_v2(image_array, index, imagename, affine)
	else:
		savemgh_v2(image_array, index, imagename, affine)
tfce_mediation/tm_func.py
def lowest_length(num_contrasts, surface_range, tmifilename, medtype = None):
	lengths = []
	for contrast in range(num_contrasts):
		for surface in surface_range: # the standardization is done within each surface
			if medtype is not None:
				lengths.append(np.array(np.genfromtxt('output_%s/perm_maxTFCE_surf%d_%s_zstat.csv' % (tmifilename,surface,medtype)).shape[0]))
			else:
				lengths.append(np.array(np.genfromtxt('output_%s/perm_maxTFCE_surf%d_tcon%d.csv' % (tmifilename,surface,contrast+1)).shape[0]))
	return np.array(lengths).min()
tfce_mediation/tm_func.py
def strip_basename(basename):
	if basename.endswith('.mgh'):
		basename = basename[:-4]
	elif basename.endswith('.nii.gz'):
		basename = basename[:-7]
	else:
		pass
	if basename.startswith('lh.all'):
		basename = 'lh.%s' % basename[7:]
	if basename.startswith('rh.all'):
		basename = 'rh.%s' % basename[7:]
	return basename
tfce_mediation/tm_func.py
def merge_adjacency_array(adjacent_range, adjacency_array):
	v_count = 0
	if len(adjacent_range) == 1:
		adjacency = np.copy(adjacency_array[0])
		for i in range(len(adjacency)):
			adjacency[i] = np.array(list(adjacency[i])).tolist() # list fixes 'set' 'int' error
	else:
		for e in adjacent_range:
			if v_count == 0:
				adjacency = np.copy(adjacency_array[0])
				for i in range(len(adjacency)):
					adjacency[i] = np.array(list(adjacency[i])).tolist() # list fixes 'set' 'int' error
				v_count += len(adjacency_array[e])
			else:
				temp_adjacency = np.copy(adjacency_array[e])
				for i in range(len(adjacency_array[e])):
					temp_adjacency[i] = np.add(list(temp_adjacency[i]), v_count).tolist() # list fixes 'set' 'int' error
				adjacency = np.hstack((adjacency, temp_adjacency))
				v_count += len(adjacency_array[e])
	return adjacency


Question: import os
import numpy as np
import argparse as ap
from time import time
from tfce_mediation.cynumstats import resid_covars
from tfce_mediation.tfce import CreateAdjSet
from tfce_mediation.tm_io import read_tm_filetype, write_tm_filetype, savemgh_v2, savenifti_v2
from tfce_mediation.pyfunc import save_ply, convert_voxel, vectorized_surface_smooth
from tfce_mediation.tm_func import calculate_tfce, calculate_mediation_tfce, calc_mixed_tfce, apply_mfwer, create_full_mask, merge_adjacency_array, lowest_length, create_position_array, paint_surface, strip_basename, saveauto
	correctionoptions.add_argument("-ssr","--setsurfacerange", 
		help="Must be used with -mfwe option. Input a range to set the surfaces to create pFWE corrected images using a range. Family-wise error rate correction will only applied to the specified surfaces. e.g., -ssr 0 3", 
		nargs=2,
		type=int,
		metavar=('INT'))

	return ap

def run(opts):
	currentTime=int(time())
	if opts.multisurfacefwecorrection:
		#############################
		###### FWER CORRECTION ######
		#############################
		_, image_array, masking_array, maskname, affine_array, vertex_array, face_array, surfname, adjacency_array, tmi_history, columnids = read_tm_filetype('%s' % opts.tmifile[0], verbose=False)

		# check file dimensions
		if not image_array[0].shape[1] % 3 == 0:
			print('Print file format is not understood. Please make sure %s is statistics file.' % opts.tmifile[0])
			quit()
		else:
			num_contrasts = int(image_array[0].shape[1] / 3)

		# get surface coordinates in data array
		position_array = create_position_array(masking_array)

		if num_contrasts == 1:
			# get lists for positive and negative contrasts
			pos_range = [1]
			neg_range = [2]
		else:
			# get lists for positive and negative contrasts
			pos_range = list(range(num_contrasts, num_contrasts+num_contrasts))
			neg_range = list(range(num_contrasts*2, num_contrasts*2+num_contrasts))

		# check that randomisation has been run
		if not os.path.exists("%s/output_%s/perm_maxTFCE_surf0_tcon1.csv" % (os.getcwd(),opts.tmifile[0])): # make this safer
			print('Permutation folder not found. Please run --randomise first.')
			quit()

		#check permutation file lengths
		num_surf = len(masking_array)
		surface_range = list(range(num_surf))
		num_perm = lowest_length(num_contrasts, surface_range, opts.tmifile[0])

		if opts.setsurfacerange:
			surface_range = list(range(opts.setsurfacerange[0], opts.setsurfacerange[1]+1))
		elif opts.setsurface:
			surface_range = opts.setsurface
		if np.array(surface_range).max() > len(masking_array):
			print("Error: range does note fit the surfaces contained in the tmi file. %s contains the following surfaces" % opts.tmifile[0])
			for i in range(len(surfname)):
				print(("Surface %d : %s, %s" % (i,surfname[i], maskname[i])))
			quit()
		print("Reading %d contrast(s) from %d of %d surface(s)" % ((num_contrasts),len(surface_range), num_surf))
		print("Reading %s permutations with an accuracy of p=0.05+/-%.4f" % (num_perm,(2*(np.sqrt(0.05*0.95/num_perm)))))

		# calculate the P(FWER) images from all surfaces
		positive_data, negative_data = apply_mfwer(image_array, num_contrasts, surface_range, num_perm, num_surf, opts.tmifile[0], position_array, pos_range, neg_range, weight='logmasksize')

		# write out files
		if opts.concatestats:
			write_tm_filetype(opts.tmifile[0],
				image_array = positive_data,
				masking_array = masking_array,
				maskname = maskname,
				affine_array = affine_array,
				vertex_array = vertex_array,
				face_array = face_array,
				surfname = surfname,
				adjacency_array = adjacency_array,
				checkname = False,
				tmi_history = tmi_history)
			_, image_array, masking_array, maskname, affine_array, vertex_array, face_array, surfname, adjacency_array, tmi_history, columnids = read_tm_filetype(opts.tmifile[0], verbose=False)
			write_tm_filetype(opts.tmifile[0],
				image_array = np.column_stack((image_array[0],negative_data)),
				masking_array = masking_array,
				maskname = maskname,
				affine_array = affine_array,
				vertex_array = vertex_array,
				face_array = face_array,
				surfname = surfname,
				adjacency_array = adjacency_array,
				checkname = False,
				tmi_history = tmi_history)
		else:
			for i in range(len(opts.outtype)):
				if opts.outtype[i] == 'tmi':
					contrast_names = []

					for j in range(num_contrasts):
						contrast_names.append(("tstat_pFWER_con%d" % (j+1)))
					for k in range(num_contrasts):
						contrast_names.append(("negtstat_pFWER_con%d" % (k+1)))

					outdata = np.column_stack((positive_data,negative_data))

					if opts.neglog:
						for j in range(num_contrasts):
							contrast_names.append(("tstat_negLog_pFWER_con%d" % (j+1)))
						for k in range(num_contrasts):
							contrast_names.append(("negtstat_negLog_pFWER_con%d" % (k+1)))

					outdata = np.column_stack((outdata,-np.log10(1-positive_data)))
					outdata = np.column_stack((outdata,-np.log10(1-negative_data)))

					write_tm_filetype("pFWER_%s" % opts.tmifile[0],
						image_array = outdata,
						masking_array = masking_array,
						maskname = maskname,
						affine_array = affine_array,
						vertex_array = vertex_array,
						face_array = face_array,
						surfname = surfname,
						checkname = False,
						columnids = np.array(contrast_names),
						tmi_history = tmi_history)

				else:
					if opts.outtype[i] == 'mgh':

Answer: 						savefunc = savemgh_v2