Raw File
import numpy as np

'''
A vectorized algorithm to calculate the 2D SF in the physical domain. 
This algorithm is significantly quicker than brute force calculation
without the sampling limitations of the frequency domain approach.

Input: data -2D array

Output: SF - 2D SF
'''

def vectorized_sf(data):

    # Calculate the length of half of each axis
    half_y = np.ma.size(data,0) / 2
    half_x = np.ma.size(data,1) / 2
     
    # Initialize bin array and bin count array
    bin_values = np.zeros((np.ma.size(data,0),np.ma.size(data,1)))
    bin_counts = np.copy(bin_values)
    
    # Loop through each pixel in data                                                                        
    for i in range(len(data)):
        for j in range(len(data[i])):

            # If a pixel is NaN, then skip it
            if not (np.isnan(data[i,j])): 
                
                # Get velocity difference squared between current pixel 
                # and every other pixel
                vdiff = (data - data[i,j])**2
                
                # Find the distances needed to center the current pixel 
                y_roll = half_y - i            
                x_roll = half_x - j
                
                # Ensure that wrapped values are set to NaN. This is done
                # because it is assumed that the input array is not periodic
                if (x_roll > 0 and y_roll > 0):
                    vdiff[(i + half_y):,(j + half_x):] = np.nan
                elif (x_roll > 0 and y_roll < 0):
                    vdiff[0:(i - half_y),(j + half_x):] = np.nan
                elif (x_roll < 0 and y_roll < 0):
                    vdiff[0:(i - half_y),0:(j - half_x)] = np.nan
                elif (x_roll < 0 and y_roll > 0):
                    vdiff[(i + half_y):,0:(j - half_x)] = np.nan   
    
                # Center the current pixel
                vdiff = np.roll(vdiff,(y_roll,x_roll),(0,1))
                
                # Find which bin counts need to be incremented
                counts = np.where(np.isnan(vdiff),0,1)
    
                # Replace NaN values with 0
                np.place(vdiff,np.isnan(vdiff),0)
                
                # Add vdiff values for current pixel to bin values array
                bin_values += vdiff

                # Add bin counts for current pixel to bin count array
                bin_counts += counts

    # Get average SF value for each bin           
    SF = bin_values/bin_counts  

    # Return SF
    return SF
    
back to top