import matplotlib.pyplot as plt
import scipy.ndimage

import csv,gc
import matplotlib
import numpy as np
import nibabel as nb

%matplotlib inline
BINS = 32

import csv,gc
import matplotlib
import numpy as np
import nibabel as nb

%matplotlib inline
BINS = 32

import sys

sys.path.append('/usr/local/lib/python2.7/site-packages')

import csv,gc
import matplotlib
import numpy as np
import cv2

#%matplotlib
BINS = 32

import matplotlib.pyplot as plt
%matplotlib inline

from skimage import data, img_as_float
from skimage import exposure

z = np.random.randint(0.0,10.0,(2,2))
print z

print z[0]
print z[1]

zz = z.reshape(-1)
print zz
print zz.sum()

plt.hist(zz, bins='auto')
plt.show()

## We expect 1 zero, 2 threes, 1 six

plt.hist(zz, bins = 10)
plt.show()

## Histogram Normalization
'''zhisteq = zz
zz.astype(float)
i=0
while i<7:
    zhisteq[i] = (zz[i]/histsum)
    i+=1
zhisteq.astype(float)
print zhisteq '''

zhistnorm = zz*1.0/sum(zz)
print zhistnorm

plt.hist(zhistnorm, bins = 7)
plt.show

"""
Explanation: Basic Array Review and Transformations
I have absolutely no idea why the below errors occur, I searched through stack exchange and apparently there is some kind of circular logic occuring, but my error was not fixed through python kernel editing unfortunately.
End of explanation
"""


import math

## Reminder of Z's values
print z

# Number of pixels
pixels = len(z) * len(z[0])
print "The number of pixels is {}".format(pixels)
## The output should be 4 since there are 4 numbers in this array

##Flatten method doesn't work because of tuple conversion later on
'''# Now we flatten Z
zz = z.reshape(-1)'''


# Initialize histogram and CDF
hist = {}
cdf = {}
norm_cdf = {}
## The range value should be be adjusted to the bin number
### In our case the range and bin number is obviously 10 
### since we generated numbers 1-10
BINS = 10

for i in range(BINS):
    hist[i] = 0
    cdf[i] = 0
    norm_cdf[i] = 0

# Create histogram


for row in z:
    for val in row:
        hist[val] += 1

'''
for val in zz:
    hist[val] += 1
'''    


# Create cdf
for i in range(BINS):
    for j in range(i+1):
        cdf[i] += hist[j]
    norm_cdf[i] = int(math.floor(float(cdf[i]-1)/63*BINS))
    
print "The histogram values are {}".format(hist)
print "The cdf values are {}".format(cdf)
print "The normalized cdf values are {}".format(norm_cdf)


"""
Explanation: Let's pretend Z is a very simple image
End of explanation
"""


newimg = np.empty(z.shape)
## This should be the same exact dimensions as the original array
print newimg 
print z.shape

## set x_length to the first number, y_length to the second
x_length = z.shape[0]
y_length = z.shape[1]

print x_length, y_length

for i in range(x_length):
    for j in range(y_length):
        newimg[i][j] = norm_cdf[ z[i][j] ]

print newimg

"""
Explanation: This matches our constructed histogram so we can proceed to create a new histogram and construct the equalized one
End of explanation
"""


img = [
    [52, 55, 61,  66,  70,  61, 64, 73],
    [63, 59, 55,  90, 109,  85, 69, 72],
    [62, 59, 68, 113, 144, 104, 66, 73],
    [63, 58, 71, 122, 154, 106, 70, 69],
    [67, 61, 68, 104, 126,  88, 68, 70],
    [79, 65, 60,  70,  77,  68, 58, 75],
    [85, 71, 64,  59,  55,  61, 65, 83],
    [87, 79, 69,  68,  65,  76, 78, 94]
]

img = np.asarray(img)
print img

print " "

print img[0]
print img[1]

print " "

imgflat = img.reshape(-1)
print imgflat
print imgflat.sum()

print " "
fig = plt.hist(imgflat, bins='auto')
plt.title('Histogram')
plt.show()

print " "

imgnorm = imgflat*1.0/sum(imgflat)
print imgnorm

fig = plt.hist(imgnorm, bins = 'auto')
plt.title('Normalized Histogram')
plt.show


import math

## Reminder of Z's values
print img

# Number of pixels
pixels = len(img) * len(img[0])
print "The number of pixels is {}".format(pixels)
## The output should be 4 since there are 4 numbers in this array

##Flatten method doesn't work because of tuple conversion later on
'''# Now we flatten Z
zz = z.reshape(-1)'''


# Initialize histogram and CDF
hist = {}
cdf = {}
norm_cdf = {}
## The range value should be be adjusted to the bin number
### In our case the range and bin number is obviously 10 
### since we generated numbers 1-10
BINS = 255

for i in range(BINS):
    hist[i] = 0
    cdf[i] = 0
    norm_cdf[i] = 0

# Create histogram


for row in img:
    for val in row:
        hist[val] += 1

'''
for val in zz:
    hist[val] += 1
'''    


# Create cdf
for i in range(BINS):
    for j in range(i+1):
        cdf[i] += hist[j]
    norm_cdf[i] = int(math.floor(float(cdf[i]-1)/63*BINS))
    
print "The histogram values are {}".format(hist)
print "The cdf values are {}".format(cdf)
print "The normalized cdf values are {}".format(norm_cdf)

newimg = np.empty(img.shape)
## This should be the same exact dimensions as the original array
print newimg 
print img.shape

## set x_length to the first number, y_length to the second
x_length = img.shape[0]
y_length = img.shape[1]

print x_length, y_length

for i in range(x_length):
    for j in range(y_length):
        newimg[i][j] = norm_cdf[ img[i][j] ]

print newimg
fig = plt.hist(newimg, bins = 'auto')
plt.title('Equalized Histogram')
plt.show

## This is wrong

for i in range(8):
    for j in range(8):
        newimg[i][j] = norm_cdf[ img[i][j] ]

print '+-------+-----------+-----+----------------+'
print '| %5s | %9s | %3s | %14s |' % ('Value', 'Histogram', 'cdf', 'Normalized cdf')
print '+-------+-----------+-----+----------------+'
for i in range(255):
    if hist[i] == 0: continue
    print '| %5s | %9s | %3s | %14s |' % (i, hist[i], cdf[i], norm_cdf[i])
print '+-------+-----------+-----+----------------+'

print ''
print 'Original subimage:'
print ''
for i in range(8):
    print ('%4d'*8) % tuple(img[i])

print ''
print ''
print 'Equalized subimage:'
print ''

for i in range(8):
    print ('%4d'*8) % tuple(newimg[i])

for i in range(x_length):
    for j in range(y_length):
        newimg[i][j] = norm_cdf[ img[i][j] ]

print newimg
fig = plt.hist(newimg, bins = 'auto')
plt.title('Equalized Histogram')
plt.show

histeqimg = np.empty(img.shape)
for i in range(8):
    histeqimg[i] = ('%4d'*8) % tuple(newimg[i])
    
    
print histeqimg
fig = plt.hist(histeqimg, bins = 'auto')
plt.title('Equalized Histogram 2')
plt.show

print(repr(histeqimg))
histeqimg.append(line.strip('\n').strip('\t').split(' ').pop(7))  
### Errors caused by massive number of zeros?

print ''
print 'Original subimage:'
print ''
for i in range(8):
    print ('%4d'*8) % tuple(img[i])
print ''
imgflat = img.reshape(-1)
print img

print " "
fig = plt.hist(imgflat, bins='auto')
plt.title('Original Histogram')
plt.show()

print ''
print ''
print 'Equalized subimage:'
print ''

for i in range(8):
    print ('%4d'*8) % tuple(newimg[i])

for i in range(x_length):
    for j in range(y_length):
        newimg[i][j] = norm_cdf[ img[i][j] ]
print ''
print newimg
fig = plt.hist(newimg, bins = 'auto')
plt.title('Equalized Histogram')
plt.show

fig = plt.hist(imgflat, bins=255)
plt.title('Original Histogram')
plt.show()

fig = plt.hist(newimg, bins = 255)
plt.title('Equalized Histogram')
plt.show

print img
print ''
print newimg
print ''

flatimg = img.reshape(-1)
flattenedimg, bin_edges1 = np.histogram(flatimg)
print flatimg
print flattenedimg
print ''

flatnewimg = newimg.reshape(-1)
flattenednewimg, bin_edges2 = np.histogram(flatnewimg)
print flatnewimg
print flattenednewimg
print ''


fig = plt.hist(flattenedimg, bins = 255)
plt.title('Original Histogram (Flat version)')
plt.show

fig = plt.hist(flattenednewimg, bins = 255)
plt.title('Equalized Histogram (Flat version)')
plt.show

a = np.random.randint(0,10,(2,2,2)) 
print a

print a[0]
print a[1]

aa = a.reshape(-1)
print aa
print aa.sum()

plt.hist(aa)
plt.show()

ahistnorm = aa*1.0/sum(aa)
print ahistnorm

plt.hist(ahistnorm, bins = 10)
plt.show

"""
Explanation: This probably didn't work because of the tiny size of the array, let's try something more established
End of explanation
"""


# 

b = np.random.randint(0,10,(2,3,4)) 
print b

print b[0]
print b[1]
print "---------"
print b[0,0]
print b[0,1]

bb = b.reshape(-1)
print bb
print bb.sum()

plt.hist(bb)
plt.show()

bhistnorm = bb*1.0/sum(bb)
print bhistnorm

plt.hist(ahistnorm, bins = 10)
plt.show

## Histogram looks different than above due to the relatively large histogram sum number

"""
Explanation: Going back to the source code to perform histogram equalization
End of explanation
"""


