Search code examples
pythonnumpysuppress-warnings

numpy "Mean of empty slice." warning


UPDATE (The real error)

I misidentified where the error was coming from. Here is my function in its entirety (sorry if some of the lines are obscure and confusing...)

def removeLines(input,CRVAL1,CDELT1): #Masks out the Balmer lines from the spectrum
    #Numbers 4060, 4150, 4300, 4375, 4800, and 4950 obtained from fit_RVs.pro.
    #Other numbers obtained from the Balmer absorption series lines
    
    for i in range(0,len(lineWindows),2):
        left = toIndex(lineWindows[i],CRVAL1,CDELT1)
        right = toIndex(lineWindows[i+1],CRVAL1,CDELT1)
        
        print "left = ", left
        print "right = ", right
        print "20 from right =\n", input[right:right+20]
        print "mean of 20 = ", numpy.mean(input[right:right+20])
        
        #Find the averages on the left and right sides
        left_avg = numpy.mean(input[left-20:left])
        right_avg = numpy.mean(input[right:right+20])   #<--- NOT here
        
        print "right_avg = ", right_avg
        
        #Find the slope between the averages
        slope = (left_avg - right_avg)/(left - right)
        
        #Find the y-intercept of the line conjoining the averages
        bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
        
        for j in range(left,right):     #Redefine the data to follow the line conjoining
            input[j] = slope*j + bval   #the sides of the peaks

    left = int(input[0])
    left_avg = int(input[0])
    right = toIndex(lineWindows[0],CRVAL1,CDELT1)
    right_avg = numpy.mean(input[right:right+20])   #<---- THIS IS WHERE IT IS!
    slope = (left_avg - right_avg)/(left - right)
    bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
    
    for i in range(left, right):
        input[i] = slope*i + bval
    return input

I have investigated the issue and found the answer, which is posted below (not in this post).


The error (The silly fake error)

#left  = An index in the data (on the 'left' side)
#right = An index in the data (on the 'right' side)
#input = The data array

print "left = ", left
print "right = ", right
print "20 from right =\n", input[right:right+20]
print "mean of 20 = ", numpy.mean(input[right:right+20])

#Find the averages on the left and right sides
left_avg = numpy.mean(input[left-20:left])
right_avg = numpy.mean(input[right:right+20])

produced the output

left =  1333
right =  1490
20 from right =
[ 0.14138737  0.14085886  0.14038289  0.14045525  0.14078836  0.14083192
  0.14072289  0.14082283  0.14058594  0.13977806  0.13955595  0.13998236
  0.1400764   0.1399636   0.14025062  0.14074247  0.14094831  0.14078569
  0.14001536  0.13895717]
mean of 20 =  0.140395
Traceback (most recent call last):
...
  File "getRVs.py", line 201, in removeLines
    right_avg = numpy.mean(input[right:right+20])
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\fromnumeric.py", line 2735, in mean
    out=out, keepdims=keepdims)
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\_methods.py", line 59, in _mean
    warnings.warn("Mean of empty slice.", RuntimeWarning)
RuntimeWarning: Mean of empty slice.

It would appear that numpy.mean runs correctly when I print it, but differently when I assign it to a value. Any feedback would be very appreciated. Thank you for taking the time to read my question.


Brief explanation

In short, I am writing a code to handle scientific data and part of the code involves taking the mean of about 20 values.

#left  = An index in the data (on the 'left' side)
#right = An index in the data (on the 'right' side)
#input = The data array

#Find the averages on the left and right sides
left_avg = numpy.mean(input[left-20:left])
right_avg = numpy.mean(input[right:right+20])

This code returns a numpy "Mean of empty slice." warning and annoyingly prints it in my precious output! I decided to try and track down the source of the warning as seen here, for example, so I placed

import warnings
warnings.simplefilter("error")

at the top of my code, which then returned the following snipped Traceback:

  File "getRVs.py", line 201, in removeLines
    right_avg = numpy.mean(input[right:right+20])
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\fromnumeric.py", line 2735, in mean
    out=out, keepdims=keepdims)
  File "C:\Users\MyName\Anaconda\lib\site-packages\numpy\core\_methods.py", line 59, in _mean
    warnings.warn("Mean of empty slice.", RuntimeWarning)
RuntimeWarning: Mean of empty slice.

I omitted about 2/3 of the Traceback because it moves through about 5 difficult-to-explain functions that do not affect the readability or size of the data.

So I decided to print out the whole operation to see if right_avg really was attempting a numpy.mean of an empty slice... And that's when things got really weird.


Solution

  • I misidentified which line of code the error sat on. What I needed to do is write in code for the specific case in which the window (left and right sides) around the center-point being considered in the data is too close to the edge of the data array.

    def removeLines(input,CRVAL1,CDELT1): #Masks out the Balmer lines from the spectrum
        
        for i in range(0,len(lineWindows),2):
            left = toIndex(lineWindows[i],CRVAL1,CDELT1)
            right = toIndex(lineWindows[i+1],CRVAL1,CDELT1)
            
            #Find the averages on the left and right sides
            left_avg = numpy.mean(input[left-20:left])
            right_avg = numpy.mean(input[right:right+20])
            
            #Find the slope between the averages
            slope = (left_avg - right_avg)/(left - right)
            
            #Find the y-intercept of the line conjoining the averages
            bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
            
            for j in range(left,right):     #Redefine the data to follow the line conjoining
                input[j] = slope*j + bval   #the sides of the peaks
    
        left = 0
        left_avg = int(input[0])
        
        if toIndex(lineWindows[0],CRVAL1,CDELT1) < 0: right = 0
        else: right = toIndex(lineWindows[0],CRVAL1,CDELT1)
    
        right_avg = numpy.mean(input[right:right+20])
        slope = (left_avg - right_avg)/(left - right)
        bval = ((left_avg - slope*left) + (right_avg - slope*right)) / 2
        
        for i in range(left, right):
            input[i] = slope*i + bval
        return input
    

    Simply change this

    right = toIndex(lineWindows[0],CRVAL1,CDELT1)    #Error occurs where right = -10
    right_avg = numpy.mean(input[right:right+20])    #Index of -10? Yeah, right.
    

    to this

    if toIndex(lineWindows[0],CRVAL1,CDELT1) < 0: right = 0    #Index 0, much better!
    else: right = toIndex(lineWindows[0],CRVAL1,CDELT1)    #Leave it alone if it isn't a problem.
    
    right_avg = numpy.mean(input[right:right+20])
    

    Also, I was wrong about left = int(input[0]), so I changed it to left = 0.