"""
This Python module is part of Pypla, a sub-project of Plastimatch (www.plastimatch.org).
Here there are some utility functions for the processing and the analysis of medical images.
All the functions accept as input mha objects (generated by mha.py) or the name of the mha files (a string).
It automatically adapts the inputs for the invoked function.

Required Python libraries:
1) numpy (http://numpy.scipy.org)
2) mha.py (another file of the Pypla project)

Author: Paolo Zaffino  (p.zaffino@unicz.it)
Rev 1

NOT TESTED ON PYTHON 3
"""


import numpy as np
import mha
from types import InstanceType


def delete_edges(ref_img, reg_img, img_out, background):
	
	"""
	This function deletes the patient outside edges that the registration task generates.

	INPUTS:
	ref_img = fixed image in the registration (mha object or string with the file name)
	reg_img = image with edges (mha object or string with the file name)
	img_out = image without edges (depending of the "ref_img" data type it can be unused, read the output section)
	background = background value (HU)

	OUTPUT:
	If the "ref_img" is a string that contains the input file name, this function will write the result in a file having
	the name as that specified in the "img_out" field (pypla_tools.delete_edeges(...)).
	If the "ref_img" is a mha object, this function will return another mha object (img=pypla_tools.delete_edeges(...))
	without write the file and so the "img_out" field will be unused.
	"""
	
	ref_img, reg_img, input_type=_adjust_inputs(ref_img, reg_img)
	
	diff=np.subtract(reg_img.data, ref_img.data)
	reg_img.data[diff==int(np.abs(background))]=background
	
	if input_type == 'file_name':
		reg_img.write_mha(img_out)
	elif input_type == 'img':
		return reg_img




def stats_img_diff (ref_img, cmp_img, threshold=50):
	
	"""
	This function computes the statistic on a image difference.
	Ideally, if two image are exactly the same, a voxel to voxel difference will return an all zeros images
	(mean and standard deviation equal to zero).
	This routine runs the subtraction and then returns the mean, the standard deviation and the percentual of voxels
	in the interval [-threshold, +threshold].
	
	INPUTS:
	ref_img = reference image (mha object or string with the file name)
	cmp_img = image to compare (mha object or string with the file name)
	threshold = abs value of the interval boundary for the compute of the percentual of the voxels around zero
				after the subraction (default is 50, not required)
	
	OUTPUTS:
	mean = mean
	std = standard deviation
	perc = percentual of voxels in the interval [-threshold, +threshold]
	"""
	
	ref_img, cmp_img, input_type=_adjust_inputs(ref_img, cmp_img)
	
	cmp_img=delete_edges(ref_img, cmp_img, 'unused_field', -1200)
	
	diff=np.subtract(ref_img.data, cmp_img.data);
	
	mean=np.mean(diff)
	std=np.std(diff)
	
	closer_HU_values=np.extract((diff <= threshold) & (diff >= -threshold), diff)
	
	elements_closer_HU_values=closer_HU_values.shape[0]
	elements_diff=diff.shape[0] * diff.shape[1] * diff.shape[2]
	perc_inside_interval=(float(elements_closer_HU_values)/float(elements_diff))*100
	
	return mean, std, perc_inside_interval




#################### UTILITY FUNCTION - START - ########################
############ PRIVATE UTILITY FUNCTION, NOT FOR PUBLIC USE ##############

def _adjust_inputs(input1, input2=''):
	
	"""
	This is a private utility function, not for public use.
	This function "adjust" the inputs for the public functions.
	If the other functions can accept both mha objects that file name strings is thanks to this routine.
	If a mha object is passed it returns the object without changes, if a file name string is passed
	it reads the file and then returns the mha object.
	
	INPUTS:
	input1= first input (mha object or string with the file name)
	input2= second input (mha object or string with the file name, not required)
	
	OUTPUTS:
	img_input1 = first adjusted input (mha object)
	img_input2 = second adjuste input (mha object, only if the "input2" was setted)
	input_type = a string, it can be "img" or "file_name". It is setted depending the "input1" data type.
	"""
	
	if type(input1)==str:
		img_input1=mha.new(input_file=input1)
		input_type='file_name'
	elif type(input1)==InstanceType:
		input_type='img'
		img_input1=input1
	
	if input2 != '':
		
		if type(input2)==str:
			img_input2=mha.new(input_file=input2)
		elif type(input2)==InstanceType:
			img_input2=input2
	
		return img_input1, img_input2, input_type
	
	elif input2 == '':
		return img_input1, input_type
		
############ PRIVATE UTILITY FUNCTION, NOT FOR PUBLIC USE ##############
##################### UTILITY FUNCTION - END - #########################
