# Path: pyBN/utils/data.py
# def unique_bins(data):
# 	"""
# 	Get the unique values for each column in a dataset.
# 	"""
# 	bins = np.empty(len(data.T), dtype=np.int32)
# 	i = 0
# 	for col in data.T:
# 		bins[i] = len(np.unique(col))
# 		i+=1
# 	return bins


import numpy as np
from scipy import stats
from pyBN.utils.data import unique_bins
				data[i,2] = ''.join(data[i,2:ncols])
			data = data.astype('int')[:,0:3]

		bins = np.amax(data,axis=0)
		hist,_ = np.histogramdd(data, bins=bins) # frequency counts

		Pxyz = hist / hist.sum()# joint probability distribution over X,Y,Z
		Pz = np.sum(Pxyz, axis = (0,1)) # P(Z)
		Pxz = np.sum(Pxyz, axis = 1) # P(X,Z)
		Pyz = np.sum(Pxyz, axis = 0) # P(Y,Z)	

		Pxy_z = Pxyz / (Pz+1e-7) # P(X,Y | Z) = P(X,Y,Z) / P(Z)
		Px_z = Pxz / (Pz+1e-7) # P(X | Z) = P(X,Z) / P(Z)	
		Py_z = Pyz / (Pz+1e-7) # P(Y | Z) = P(Y,Z) / P(Z)

		Px_y_z = np.empty((Pxy_z.shape)) # P(X|Z)P(Y|Z)
		for i in range(bins[0]):
			for j in range(bins[1]):
				for k in range(bins[2]):
					Px_y_z[i][j][k] = Px_z[i][k]*Py_z[j][k]
		Pxyz += 1e-7
		Pxy_z += 1e-7
		Px_y_z += 1e-7
		MI = np.sum(Pxyz * np.log(Pxy_z / (Px_y_z)))
		
		return round(MI,4)
	elif len(bins) > 2 and conditional == False:
		data = data.astype('str')
		ncols = len(bins)
		for i in range(len(data)):

# Path: pyBN/utils/data.py
# def unique_bins(data):
# 	"""
# 	Get the unique values for each column in a dataset.
# 	"""
# 	bins = np.empty(len(data.T), dtype=np.int32)
# 	i = 0
# 	for col in data.T:
# 		bins[i] = len(np.unique(col))
# 		i+=1
# 	return bins


# Path: pyBN/utils/independence_tests.py
import numpy as np
from scipy import stats
from pyBN.utils.data import unique_bins

				data[i,2] = ''.join(data[i,2:ncols])
			data = data.astype('int')[:,0:3]

		bins = np.amax(data,axis=0)
		hist,_ = np.histogramdd(data, bins=bins) # frequency counts

		Pxyz = hist / hist.sum()# joint probability distribution over X,Y,Z
		Pz = np.sum(Pxyz, axis = (0,1)) # P(Z)
		Pxz = np.sum(Pxyz, axis = 1) # P(X,Z)
		Pyz = np.sum(Pxyz, axis = 0) # P(Y,Z)	

		Pxy_z = Pxyz / (Pz+1e-7) # P(X,Y | Z) = P(X,Y,Z) / P(Z)
		Px_z = Pxz / (Pz+1e-7) # P(X | Z) = P(X,Z) / P(Z)	
		Py_z = Pyz / (Pz+1e-7) # P(Y | Z) = P(Y,Z) / P(Z)

		Px_y_z = np.empty((Pxy_z.shape)) # P(X|Z)P(Y|Z)
		for i in range(bins[0]):
			for j in range(bins[1]):
				for k in range(bins[2]):
					Px_y_z[i][j][k] = Px_z[i][k]*Py_z[j][k]
		Pxyz += 1e-7
		Pxy_z += 1e-7
		Px_y_z += 1e-7
		MI = np.sum(Pxyz * np.log(Pxy_z / (Px_y_z)))
		
		return round(MI,4)
	elif len(bins) > 2 and conditional == False:
		data = data.astype('str')
		ncols = len(bins)
		for i in range(len(data)):

			data[i,1] = ''.join(data[i,1:ncols])