I'm trying to make a histogram of some data that is being stored in an ndarray. The histogram is part of a set of analysis which I've made into a class in a python program. The part of the code that isn't working is below.
def histogram(self, iters):
samples = T.MCMC(iters) #Returns an [iters,3,4] ndarray
histAC = plt.figure(self.ip) #plt is matplotlib's pyplot
self.ip+=1 #defined at the beginning of the class to start at 0
for l in range(0,4):
h = histAC.add_subplot(2,(iters+1)/2,l+1)
for i in range(0,0.5*self.chan_num):
intAvg = mean(samples[:,i,l])
print intAvg
for k in range(0,iters):
samples[k,i,l]=samples[k,i,l]-intAvg
print "Samples is ",samples
h.hist(samples,bins=5000,range=[-6e-9,6e-9],histtype='step')
h.legend(loc='upper right')
h.set_title("AC Pulse Integral Histograms: "+str(l))
figname = 'ACHistograms.png'
figpath = 'plot'+str(self.ip)
print "Finished!"
#plt.savefig(figpath + figname, format = 'png')
This gives me the following error message:
File "johnmcmc.py", line 257, in histogram
h.hist(samples,bins=5000,range=[-6e-9,6e-9],histtype='step') #removed label=apdlabel
File "/x/tsfit/local/lib/python2.6/site-packages/matplotlib/axes.py", line 7238, in hist
ymin = np.amin(m[m!=0]) # filter out the 0 height bins
File "/x/tsfit/local/lib/python2.6/site-packages/numpy/core/fromnumeric.py", line 1829, in amin
return amin(axis, out)
ValueError: zero-size array to ufunc.reduce without identity
The only search results I've found have been multiple copies of the same two conversations, from which the only thing I learned was that python histograms don't like getting fed empty arrays, which is why I added the print statement right above the line that's giving me trouble to make sure the array isn't empty.
Has anyone else come across this error before?
Related
I am trying to create N-Dimensional histogram from 2D array which has complex values. I want to count the number of occurrences in real and imaginary parts of the array given the bins and store the result in a 3D array. It only runs for the first iteration when I hard code i=0 and remove the for loop. I have never used histograms in python before and I just cannot understand the error. The code is given below.
xsoft is defined as 2d array of complex type and I somehow compute bnd_edges by finding max, min values from xsoft and create edges to be given as bins.
xsoft = np.empty((M, MAX,), dtype=complex) # e.g has dims 4*100
xsoft[:] = np.nan
edges = np.linspace(-bnd_edges, bnd_edges, numbin) #numbin=10
pSOFT = np.empty((len(edges)-1, M, len(edges)-1)) # len(edges)= 10
pSOFT[:] = np.nan
for i in range(M):
pSOFT[:, i, :], edges = np.histogramdd((xsoft[i, :].real, xsoft[i, :].imag), bins=(edges, edges))
The code results in the following error
Traceback (most recent call last):
File " ", line 194, in <module>
pSOFT[:, i, :], edges = np.histogramdd((xsoft[i, :].real, xsoft[i, :].imag), bins=(edges, edges))
File "<__array_function__ internals>", line 5, in histogramdd
File " " line 1066, in histogramdd
raise ValueError(
ValueError: `bins[0]` must be a scalar or 1d array
Process finished with exit code 1
You are getting this error because you are overriding the original definition of edges with the second return value of histogramdd.
Replace the last line in your code with this:
pSOFT[:, i, :], edges_i = np.histogramdd((xsoft[i, :].real, xsoft[i, :].imag), bins=(edges, edges))
I want to create a program that takes a picture of the same area at 2 different times and then compares the images, and then creates an entirely new image that has just the difference between the 2 images (what changed). I am using RGB values and I am looking to see if they are more than 90% different in value then I want to add those pixels to the new matrix, which will be mapped.
I am fairly new to Raspberry Pi and python so I ran into an error and I don't understand why it is giving me that error.
I have tried using both PIL and Numpy but both methods produce errors that I can't fix
THIS ISN'T THE ENTIRE CODE, BUT THIS IS THE FUNCTION THAT IS GIVING ME THE ERROR:
from PIL import Image
import numpy as np
import picamera
import time
import RPi.GPIO
from guizero import ...
def processimage():
before = Image.open('before.jpg')
after = Image.open('after.jpg')
beforeRGB = np.array(before)
afterRGB = np.array(after)
outputRGB = Image.new('RGB', (800,480))
x=0
y=0
for x in range(800):
for y in range(480):
if(((beforeRGB[x,y,0])/afterRGB[x,y,0])<0.9):
outputRGB[x,y,0] = afterRGB[x,y,0]
else:
output[x,y,0] = 255
if(((beforeRGB[x,y,1])/afterRGB[x,y,1])<0.9):
outputRGB[x,y,1] = afterRGB[x,y,1]
else:
output[x,y,1] = 255
if(((beforeRGB[x,y,2])/afterRGB[x,y,2])<0.9):
outputRGB[x,y,2] = afterRGB[x,y,2]
else:
output[x,y,2] = 255
y=y+1
x=x+1
Image.fromarray(outputRGB).save('output.jpg')
THIS IS THE ERROR I AM GETTING
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/__init__.py", line 1562, in __call__
return self.func(*args)
File "/usr/local/lib/python3.5/dist-packages/guizero/PushButton.py",
line 146, in _command_callback
self._command()
File "/home/pi/ButtonTest/GUI_interface.py", line 70, in mode
lifetime(key)
File "/home/pi/ButtonTest/GUI_interface.py", line 158, in lifetime
processimage()
File "/home/pi/ButtonTest/GUI_interface.py", line 115, in processimage
outputRGB[x,y,0] = afterRGB(x,y,0)
TypeError: 'numpy.ndarray' object is not callable
1) The error message doesn't match the code. The error message is about a different version of the code where () where used accidentally instead of [], see last code line of the error message.
2) Iterating over individual pixels is very slow when using Python. Please read through a couple of image processing tutorials to get an understanding of vectorization and broadcasting.
For example, the code above could be shortened to something like:
output = np.where(beforeRGB/afterRGB < 0.9, afterRGB, 255]
3) for x in range() already iterates over all x values in the range. There is no need to increment x or y at the end of the loop.
4) The formula chosen for the image difference produces division by zero for pixels where at least one of the channels is 0. Do some research and choose a better metric for image differences.
I'm trying to use plt.text to plot temperature values at their associated lat/lon points on a plot.
After reviewing the plt.text documentation, it appears that the plotted value (third arg) has to be a number and that the number has to be a whole number, NOT a number with decimals.
Below is the code that I'm trying to work with and the associated traceback error that I'm receiving:
Script Code:
data = np.loadtxt('/.../.../.../tmax_day0', delimiter=',', skiprows=1)
grid_x, grid_y = np.mgrid[-85:64:dx, 34:49:dx]
temp = data[:,2]
#print temp
grid_z = griddata((data[:,1],data[:,0]), data[:,2], (grid_x,grid_y), method='linear')
x,y = m(data[:,1], data[:,0]) # flip lat/lon
grid_x,grid_y = m(grid_x,grid_y)
#m.plot(x,y, 'ko', markersize=2)
def str_to_float(str):
try:
number = float(str)
except ValueError:
number = 0.0
return number
fmt = str_to_float(temp)
#annotate point temperature on plot
plt.text(grid_x, grid_y, fmt, fontdict=None)
Traceback Error:
Traceback (most recent call last):
File "plotpoints.py", line 56, in <module>
fmt = str_to_float(temp)
File "plotpoints.py", line 51, in str_to_float
number = float(str)
TypeError: only length-1 arrays can be converted to Python scalars
Data sample from text file tmax_day0:
latitude,longitude,value
36.65408,-83.21783,90
41.00928,-74.73628,92.02
43.77714,-71.75598,90
44.41944,-72.01944,88.8
39.5803,-79.3394,79
38.3154,-76.5501,86
38.91444,-82.09833,94
40.64985,-75.44771,92.6
41.25389,-70.05972,81.2
39.45202,-74.56699,90.88
I was able to achieve plotting data values only by using the following code:
for i in range(len(temp)):
plt.text(x[i], y[i], temp[i], va="top", family="monospace")
Result:
You aren't using a "proper" array, and are instead using a numpy array. Numpy arrays don't play well with non-numpy functions.
Going from your comment, this has been edited.
You would first need to fix the string so it's a proper array.
fmt = fmt[0].split()
I think should work to create a new (normal) array of strings. And then this to map that to an array of floats:
list_of_floats = np.array(map(float, fmt))
I have two pictures, one that was the original and another one that I have modified so that it's translated up and left a bit and then rotated 90 degrees (so the shape of the picture is transposed as well).
Now I'd like to determine how many pixels (or any distance unit) the modified picture is translated from the original, as well as the degrees of rotation relative to the original. Phase correlation is supposed to solve this problem by first converting the coordinates to logpolar coordinates, then doing a number of things so that in the end you get a correlation matrix. From that matrix I'm supposed to find the peak and the (x,y) combination will reveal the translation and rotation somehow. This link explains it much better:
Phase correlation
This is the following code I have:
import scipy as sp
from scipy import ndimage
from PIL import Image
from math import *
import numpy as np
def logpolar(input,silent=False):
# This takes a numpy array and returns it in Log-Polar coordinates.
if not silent: print("Creating log-polar coordinates...")
# Create a cartesian array which will be used to compute log-polar coordinates.
coordinates = sp.mgrid[0:max(input.shape)*2,0:360]
# Compute a normalized logarithmic gradient
log_r = 10**(coordinates[0,:]/(input.shape[0]*2.)*log10(input.shape[1]))
# Create a linear gradient going from 0 to 2*Pi
angle = 2.*pi*(coordinates[1,:]/360.)
# Using scipy's map_coordinates(), we map the input array on the log-polar
# coordinate. Do not forget to center the coordinates!
if not silent: print("Interpolation...")
lpinput = ndimage.interpolation.map_coordinates(input,
(log_r*sp.cos(angle)+input.shape[0]/2.,
log_r*sp.sin(angle)+input.shape[1]/2.),
order=3,mode='constant')
# Returning log-normal...
return lpinput
def load_image( infilename ) :
img = Image.open( infilename )
img.load()
data = np.asarray( img, dtype="int32" )
return data
def save_image( npdata, outfilename ) :
img = Image.fromarray( np.asarray( np.clip(npdata,0,255), dtype="uint8"), "L" )
img.save( outfilename )
image = load_image("C:/images/testing_image1.jpg")
target = load_image("C:/images/testing_otherimage.jpg")
# Conversion to log-polar coordinates
lpimage = logpolar(image)
lptarget = logpolar(target)
# Correlation through FFTs
Fcorr = np.fft.fft(lpimage)*np.fft.fft(lptarget)
correlation = np.fft.ifft(Fcorr)
The problem I have now is that this code will give as output:
Traceback (most recent call last):
File "./phase.py", line 44, in <module>
lpimage = logpolar(image)
File "./phase.py", line 24, in logpolar
order=3,mode='constant')
File "C:\Python27\lib\site-packages\scipy\ndimage\interpolation.py", line 295, in map_coordinates
raise RuntimeError('invalid shape for coordinate array')
RuntimeError: invalid shape for coordinate array
As I just have a very superficial understanding of what exactly is happening in the whole phase correlation process, I'm unclear on what the problem is about. I have tried to see if something's wrong with the input so I added save_image(image,"C:/testing.jpg") right after loading the image to see if there's something wrong with the numpy array from my images. And sure enough, the images I convert to np array, cannot be converted back to an image. This is the error I get:
Traceback (most recent call last):
File "./phase.py", line 41, in <module>
save_image(image,"C:/testing.jpg")
File "./phase.py", line 36, in save_image
img = Image.fromarray( np.asarray( np.clip(npdata,0,255), dtype="uint8"), "L" )
File "C:\Python27\lib\site-packages\PIL\Image.py", line 1917, in fromarray
raise ValueError("Too many dimensions.")
ValueError: Too many dimensions.
Taking a peek at the original documentation didn't give me much inspiration on what the problem could be. I don't think the code to convert images to numpy arrays are wrong as I've tested for the type with print type(image) and the results looked legit. Yet I can't convert it back to an image. Any help I can get would be greatly appreciated.
I think the problem is that you are trying to input a 3D image array (R,G,B,A?), into your function. Whereas the input only takes a 2D arrays. Try using a single channel to determine the transformation. E.g.
image = load_image("/path/to/image")[:,:,0]
I am trying to convert an image from cartesian to polar so that I can unravel the image, but I am getting a runtime error. If you are curious how this looks visually, see this example.
Code:
import scipy
import scipy.ndimage
import numpy as np
from math import *
import cv2
def logpolar(input):
# This takes a numpy array and returns it in Log-Polar coordinates.
coordinates = np.mgrid[0:max(input.shape[:])*2,0:360] # We create a cartesian array which will be used to compute log-polar coordinates.
log_r = 10**(coordinates[0,:]/(input.shape[0]*2.)*log10(input.shape[1])) # This contains a normalized logarithmic gradient
angle = 2.*pi*(coordinates[1,:]/360.) # This is a linear gradient going from 0 to 2*Pi
# Using scipy's map_coordinates(), we map the input array on the log-polar coordinate. Do not forget to center the coordinates!
lpinput = scipy.ndimage.interpolation.map_coordinates(input,(log_r*np.cos(angle)+input.shape[0]/2.,log_r*np.sin(angle)+input.shape[1]/2.),order=3,mode='constant')
# Returning log-normal...
return lpinput
# Load image
image = cv2.imread("test.jpg")
result = logpolar(image)
Error message in console:
Traceback (most recent call last):
File "test.py", line 23, in <module>
result = logpolar(image)
File "test.py", line 15, in logpolar
lpinput = scipy.ndimage.interpolation.map_coordinates(input,(log_r*np.cos(angle)+input.shape[0]/2.,log_r*np.sin(angle)+input.shape[1]/2.),order=3,mode='constant')
File "/Library/Python/2.7/site-packages/scipy-0.13.0.dev_c31f167_20130415-py2.7-macosx-10.8-intel.egg/scipy/ndimage/interpolation.py", line 295, in map_coordinates
raise RuntimeError('invalid shape for coordinate array')
RuntimeError: invalid shape for coordinate array
My first guess would be that you are passing in a colour image which is 3 dimensional. At first glance I don't think your code could handle that.
My guess was based off of the error you pasted, specifically
"invalid shape for coordinate array"
When using higher dimensional arrays like that usually you have to pass extra parameters around specifying which axis to repeat the operations over and even then sometimes it does not work. I didn't see a repeated extra integer at the end of your argument lists so I figured you weren't trying to handle that case explicitly and might have forgotten to check your array dimensions after reading in the image.
Glad it helped :)