示例#1
0
    def plot_corr_mat_btn_clicked(self):
        """This function calls a pop up window which shows the correlation matrix"""

        self.calc_cor_matrix = openpiv.process.correlate_windows(
            window_a=self.small_windows[
                self.iw_pos_x_value /
                (self.iw_big_size_value - self.overlap_size_value) +
                (self.iw_pos_y_value /
                 (self.iw_big_size_value - self.overlap_size_value)) *
                self.field_shape[1]].astype(np.float64),
            window_b=self.big_windows[
                self.iw_pos_x_value /
                (self.iw_big_size_value - self.overlap_size_value) +
                (self.iw_pos_y_value /
                 (self.iw_big_size_value - self.overlap_size_value)) *
                self.field_shape[1]].astype(np.float64),
            corr_method='fft',
            nfftx=None,
            nffty=None)

        self.corr_mat_plt = Window(self.calc_cor_matrix.shape[0],
                                   self.calc_cor_matrix.shape[1],
                                   self.calc_cor_matrix,
                                   self.main_slider_value)

        self.corr_mat_plt.show()
示例#2
0
    def plot_corr_mat_btn_clicked(self):
        """This function calls a pop up window which shows the correlation matrix"""
        
        calc_cor_matrix = openpiv.process.correlate_windows( window_a = self.small_windows[self.iw_pos_x_value/(self.iw_big_size_value - self.overlap_size_value) + (self.iw_pos_y_value/(self.iw_big_size_value- self.overlap_size_value))*self.field_shape[1]].astype(np.float64), window_b = self.big_windows[self.iw_pos_x_value/(self.iw_big_size_value - self.overlap_size_value) + (self.iw_pos_y_value/(self.iw_big_size_value- self.overlap_size_value))*self.field_shape[1]].astype(np.float64), corr_method = 'fft', nfftx = None, nffty = None )

        self.corr_mat_plt = Window(calc_cor_matrix.shape[0],calc_cor_matrix.shape[1],calc_cor_matrix, self.main_slider_value)
        self.corr_mat_plt.show()
示例#3
0
class Main(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.ui = Ui_Form()
        self.ui.setupUi(self)

        #get the frames and sort them (need a leading zero). 
        ###TODO: functionalize the load button to choose the directory of the images/(type?).
        self.frames = sorted(glob.glob('./*.png'))
        self.raw_frames = sorted(glob.glob('./raw/*.bmp'))
        self.frame_size_x = scipy.misc.imread(self.frames[0]).shape[1]
        self.frame_size_y = scipy.misc.imread(self.frames[0]).shape[0]
        
        #set some default values. 
        ###TODO:These values should be automatically set to whatever IW/overlap sizes were set in the analysis.
        self.iw_small_size_value = 32
        self.iw_big_size_value = 64
        self.overlap_size_value = 48
        self.ui.iw_small_size.setValue(self.iw_small_size_value )
        self.ui.iw_big_size.setValue(self.iw_big_size_value)
        self.ui.iw_overlap_size.setValue(self.overlap_size_value )

        #set the maximum overlap value
        self.ui.iw_overlap_size.setMaximum(self.iw_big_size_value-1)
        self.subwindow_inset = (self.iw_big_size_value-self.iw_small_size_value)/2
        self.iw_pos_x_value = 0
        self.iw_pos_y_value = 0
        self.main_slider_value = 0
        
        #setup next/previous buttons
        self.ui.next_frame.clicked.connect(lambda: self.set_slider(+1))
        self.ui.prev_frame.clicked.connect(lambda: self.set_slider(-1))
        
        #setup main slider
        self.ui.main_slider_value.valueChanged.connect(self.main_slider_value_changed)
        self.ui.main_slider_value.setMaximum(len(self.frames)-1)
        
        #setup IW/overlap size input boxes
        self.ui.iw_small_size.valueChanged.connect(self.set_small_iw_size)
        self.ui.iw_big_size.valueChanged.connect(self.set_big_iw_size)
        self.ui.iw_overlap_size.valueChanged.connect(self.set_iw_overlap_size)
        
        #setup maximum values for iw sliders
        self.ui.iw_pos_x.setMaximum( (self.frame_size_x - self.iw_big_size_value)/self.iw_big_size_value )
        self.ui.iw_pos_y.setMaximum( (self.frame_size_y - self.iw_big_size_value )/self.iw_big_size_value )
        
        #setup iw sliders
        self.ui.iw_pos_x.valueChanged.connect(self.iw_pos_x_slider_value)
        self.ui.iw_pos_y.valueChanged.connect(self.iw_pos_y_slider_value)
        
        #setup redraw iws checkbox and its auxilary function
        self.ui.redraw_iws.stateChanged.connect(self.check_state)
        self.state = self.ui.redraw_iws.isChecked()
        
        #setup plot correlation matrix button
        self.ui.plot_corr_mat.clicked.connect(self.plot_corr_mat_btn_clicked)
        
        #set up the initial images on the GUI, so it would look better
        self.main_pixmap = QtGui.QPixmap(self.frames[0])
        self.draw_iw_bounds(self.main_pixmap)
        self.ui.label_main.setPixmap(self.main_pixmap)
        self.display_small_iw()
        self.display_big_iw()
        
        #reference image for getting intensity values...
        self.main_pixmap_ref_array = scipy.misc.imread((self.raw_frames[0]))
        
        #update iw slider max
        self.update_iw_slider_max()
        
        #Sets up mouse action on main window (not tested with scaling...)
        self.ui.label_main.mousePressEvent = self.getPos  
        

    #######################
    #GUI specific functions
    #######################
    
    def getPos(self , event):
        """Prints the position of the mouse click and corresponding intensity value on the main image. The print out happens in the console"""
        x = event.pos().x()
        y = event.pos().y()
        c = self.main_pixmap_ref_array[y][x]
        print 'x,y,int =',x,y,c    
        
    def set_slider(self,delta):
        """Changes the main frame slider by singleStep value when next/prev buttons are clicked."""
        self.ui.main_slider_value.setValue(self.ui.main_slider_value.value() + delta * self.ui.main_slider_value.singleStep())
    
    def update_iw_slider_max(self):
        """Enables the sliders to be 'draged by mouse' and to match the IW positions."""
        #It seems that there is no nice and simple way to be able to use "mouse sliding" of sliders so that the values would not move at arbitrary points, but to exact IW positions. One workaround is to set the maximum value of the slider to the one divided by the big IW size. However, we must take into account that we might have an overlap. This means quite a long expression, but the code could probably be cleaned up a bit by setting the "self.iw_big_size_value - self.overlap_size_value" to a single instance variable at init. It gets particularly messy in display_small/big_iw functions...
        self.ui.iw_pos_x.setMaximum( (scipy.misc.imread(self.frames[0]).shape[1] - self.iw_big_size_value )/(self.iw_big_size_value - self.overlap_size_value ) )
        self.ui.iw_pos_y.setMaximum( (scipy.misc.imread(self.frames[0]).shape[0] - self.iw_big_size_value )/(self.iw_big_size_value - self.overlap_size_value ) )
        
    def update_overlap_max(self):
        """Updates the big IW overlap size."""
        #We should not allow the overlap value to exceed the big IW value, as that will result in an error
        self.ui.iw_overlap_size.setMaximum(self.iw_big_size_value-1)
        
    def update_subwindow_inset(self):
        """Updates the subwindow inset"""
        self.subwindow_inset = (self.iw_big_size_value-self.iw_small_size_value)/2
                
    def set_small_iw_size(self, value):             
        """Takes the input value for the small IW size from the gui and sets it as an instance variable."""
        self.iw_small_size_value = value
        #the gui should only allow integers, but just in case we have an assertion.
        assert isinstance(value, int)
        self.update_subwindow_inset()
        self.display_main_image()
        
    def set_big_iw_size(self, value):
        """Takes the input value for the big IW size from the gui and sets it as an instance variable."""
        self.iw_big_size_value = value
        assert isinstance(value, int)
        self.display_main_image()
        self.update_subwindow_inset()
        self.update_iw_slider_max()
        self.update_overlap_max()
        
    def set_iw_overlap_size(self, value):
        """Takes the input value for the big IW overlap size from the gui and sets it as an instance variable."""
        self.overlap_size_value = value
        assert isinstance(value, int)
        self.display_main_image()
        self.update_iw_slider_max()
        
    def iw_pos_x_slider_value(self,value):
        """Functionality triggered by moving horizontal iw slider"""
        self.iw_pos_x_value = value*(self.iw_big_size_value - self.overlap_size_value)
        assert isinstance(value, int)
        self.display_main_image()
        self.display_small_iw()
        self.display_big_iw()
        
    def iw_pos_y_slider_value(self,value):
        """Functionality trigerred by moving vertical iw slider"""
        self.iw_pos_y_value = value*(self.iw_big_size_value - self.overlap_size_value)
        assert isinstance(value, int)
        self.display_main_image()
        self.display_small_iw()
        self.display_big_iw()
        
    def main_slider_value_changed(self,new_value):
        """Gets the main slider value and draws the main image"""   
        self.main_slider_value = new_value
        assert isinstance(new_value, int)
        self.display_main_image()
    
    
    def display_main_image(self):
        """Displays the main image."""
        self.main_pixmap = QtGui.QPixmap(self.frames[self.main_slider_value])
        #Reference image updated...
        self.main_pixmap_ref_array = scipy.misc.imread(self.raw_frames[self.main_slider_value])
        #Draws IW bounds
        self.draw_iw_bounds(self.main_pixmap)
        ####TODO: scale the whole thing. see http://stackoverflow.com/questions/24106903/resizing-qpixmap-while-maintaining-aspect-ratio, http://stackoverflow.com/questions/21041941/how-to-autoresize-qlabel-pixmap-keeping-ratio-without-using-classes
        ####TODO: enable zooming
        self.ui.label_main.setPixmap(self.main_pixmap)    
        #Updates the IW images if necessary.
        self.replot_iws()
        
    def draw_iw_bounds(self,main_pixmap):
        """Draws the rectangles of IW window sizes on the main image. The centre is indicated by a green dot."""
        
        draw = QtGui.QPainter(self.main_pixmap)
        draw.setBrush(QtCore.Qt.NoBrush)
        draw.setPen(QtCore.Qt.blue)
        #Draw the small IW centered on the big IW.drawRect takes (x,y, width, height). Check what happens if the value is NOT divisible by 2.
        draw.drawRect(self.iw_pos_x_value + (self.iw_big_size_value - self.iw_small_size_value)/2, self.iw_pos_y_value + (self.iw_big_size_value - self.iw_small_size_value)/2, self.iw_small_size_value,self.iw_small_size_value )
        draw.setPen(QtCore.Qt.red)
        #Draw the big IW
        draw.drawRect(self.iw_pos_x_value, self.iw_pos_y_value, self.iw_big_size_value, self.iw_big_size_value)
        draw.setPen(QtCore.Qt.green)
        #Draw a point in the centre of the two IWs.
        draw.drawPoint(self.iw_big_size_value/2 + self.iw_pos_x_value, self.iw_big_size_value/2 + self.iw_pos_y_value)    

    def display_small_iw(self):    
        """Displays the small IW. Uses an extension of moving_window_array function from openpiv.The frame from which small_IWs are obtained are called frame_a or "first" frame, since we assume positive time change and frame_a is compared to frame_b. So in positive time change, and appropriate flow conditions, the big_iw should preserve the information from small_iw, hence minimising in-plane information loss."""
        
        frame_a = scipy.misc.imread(self.raw_frames[self.main_slider_value])
        self.small_windows = self.moving_sub_window_array(frame_a, self.iw_big_size_value, self.overlap_size_value, self.subwindow_inset)
        
        #field shape provides the information how many big IWs fit in the frame of interest.
        self.field_shape = openpiv.process.get_field_shape(image_size = scipy.misc.imread(self.raw_frames[self.main_slider_value]).shape, window_size = self.iw_big_size_value, overlap = self.overlap_size_value)
        
        ###TODO: try and make this more readable. Automate scaling?
        self.pixmap_small_iw = QtGui.QPixmap.fromImage(ImageQt.ImageQt(scipy.misc.toimage(self.small_windows[self.iw_pos_x_value/(self.iw_big_size_value - self.overlap_size_value) + (self.iw_pos_y_value/(self.iw_big_size_value- self.overlap_size_value))*self.field_shape[1]], cmax = 255, cmin = 0))).scaled(64, 64, QtCore.Qt.KeepAspectRatio)
        self.ui.label_small_iw.setPixmap(self.pixmap_small_iw)
        
      
    def display_big_iw(self):   
        """Displays the big IW. Uses modified moving_window_array function from openpiv.The frame from which big_IWs are obtained are called frame_b or "second" frame, since we assume positive time change and frame_a is compared to frame_b."""
        
        ###TODO: make sure this is consistent with openpiv correlation.
        frame_b = scipy.misc.imread(self.raw_frames[self.main_slider_value + 1])
        self.big_windows = self.moving_window_array(frame_b, self.iw_big_size_value, self.overlap_size_value)
        
        ###TODO: try and make this more readable. Automate scaling?
        self.pixmap_big_iw = QtGui.QPixmap.fromImage(ImageQt.ImageQt(scipy.misc.toimage(self.big_windows[self.iw_pos_x_value/(self.iw_big_size_value - self.overlap_size_value) + (self.iw_pos_y_value/(self.iw_big_size_value- self.overlap_size_value))*self.field_shape[1]], cmax = 255, cmin = 0))).scaled(128, 128, QtCore.Qt.KeepAspectRatio)
        
        ###TODO: need to check if setting same cmin,cmax for the small/big IW images does give the SAME dynamic range.
        self.ui.label_big_iw.setPixmap(self.pixmap_big_iw)        
        
    def check_state(self,state):
        """Calls replot_iws when checkbox state is changed so that IW's would get updated without changing the frame/IW position"""
        self.replot_iws()    
    
    def replot_iws(self):
        """Sometimes it might be useful to redraw the IWs from previous frame matching, for instance, is there is a need to switch between two main frames, to see the "big picture" flow. """
        
        self.state = self.ui.redraw_iws.isChecked()
        if self.state == True:
            self.display_small_iw()
            self.display_big_iw()
        else:
            pass

    def plot_corr_mat_btn_clicked(self):
        """This function calls a pop up window which shows the correlation matrix"""
        
        calc_cor_matrix = openpiv.process.correlate_windows( window_a = self.small_windows[self.iw_pos_x_value/(self.iw_big_size_value - self.overlap_size_value) + (self.iw_pos_y_value/(self.iw_big_size_value- self.overlap_size_value))*self.field_shape[1]].astype(np.float64), window_b = self.big_windows[self.iw_pos_x_value/(self.iw_big_size_value - self.overlap_size_value) + (self.iw_pos_y_value/(self.iw_big_size_value- self.overlap_size_value))*self.field_shape[1]].astype(np.float64), corr_method = 'fft', nfftx = None, nffty = None )

        self.corr_mat_plt = Window(calc_cor_matrix.shape[0],calc_cor_matrix.shape[1],calc_cor_matrix, self.main_slider_value)
        self.corr_mat_plt.show()
        
        
    #################
    #Helper functions
    #################
    
    def moving_window_array(self, array, window_size, overlap):
        """Returns what the original openpiv moving_window_array function did."""
        return self.moving_sub_window_array(array, window_size, overlap, 0)

    def moving_sub_window_array( self, array, window_size, overlap, subwindow_inset ):
        """
        Parameters
        ----------
        array = 3D image array that we want to access in terms of its IWs

        window_size = size of each large IW

        overlap = overlap between adjacent large IWs

        subwindow_inset = the size of how far away from the boundary we push the centre of the smaller window (similar to cropping).
                            This can be set to 0 if we want to obtain the array used to access the large IW.
                            
        Written by Dr Jonathan Taylor. Based on moving_window_array function in OpenPIV (www.openpiv.net).
        """
        # The implementation of this function is rather complicated, involving the use of numpy's stride_tricks library.
        # The intention is to provide a 3D array that can be indexed using the parameters: IW index, x coord within IW, y coord within IW.
        # In order to achieve this we create a 4D array (IW x index, IW y index, ...), and flatten the first two dimensions into one.
        # Creating a 4D array like this is "relatively" easy using stride_tricks in the case where the first IW starts at (0,0).
        # However, things get a little harder if we want to create an array of small IWs, since these are inset and hence do not start at (0,0).
        # They start at (subwindow_inset, subwindow_inset). In order to achieve that we actually need to create a *fifth* dimension to
        # our intermediate array, with a stride that takes us from (0,0) to the correct starting point. We then pick out the second
        # array element in that dimension, which gives us what we want.
        sz = array.itemsize
        shape = array.shape
        subwindow_size = window_size - 2*subwindow_inset
        assert(subwindow_size > 0)
        strides = (sz*(shape[1]*subwindow_inset+subwindow_inset), sz*shape[1]*(window_size-overlap), sz*(window_size-overlap), sz*shape[1], sz)
        shape = (2, int((shape[0] - window_size)/(window_size-overlap))+1, int((shape[1] - window_size)/(window_size-overlap))+1 , subwindow_size, subwindow_size)
        return np.lib.stride_tricks.as_strided( array, strides=strides, shape=shape )[1,:,:,:,:].reshape(-1, subwindow_size, subwindow_size)
示例#4
0
 def __init__(self):
     super().__init__()
     self.ui = Window()
     self.ui.setup_ui(self)
     self.show()
示例#5
0
class Main(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.ui = Ui_Form()
        self.ui.setupUi(self)

        #get the frames and sort them (need a leading zero).
        ###TODO: functionalize the load button to choose the directory of the images/(type?).
        self.frames = sorted(glob.glob('./*.png'))
        self.raw_frames = sorted(glob.glob('./raw/*.bmp'))
        self.frame_size_x = scipy.misc.imread(self.raw_frames[0]).shape[1]
        self.frame_size_y = scipy.misc.imread(self.raw_frames[0]).shape[0]

        #set some default values.
        ###TODO:These values should be automatically set to whatever IW/overlap sizes were set in the analysis.
        self.iw_small_size_value = 32
        self.iw_big_size_value = 64
        self.overlap_size_value = 48
        self.ui.iw_small_size.setValue(self.iw_small_size_value)
        self.ui.iw_big_size.setValue(self.iw_big_size_value)
        self.ui.iw_overlap_size.setValue(self.overlap_size_value)

        #set the maximum overlap value
        self.ui.iw_overlap_size.setMaximum(self.iw_big_size_value - 1)
        self.subwindow_inset = (self.iw_big_size_value -
                                self.iw_small_size_value) / 2
        self.iw_pos_x_value = 0
        self.iw_pos_y_value = 0
        self.main_slider_value = 0

        #setup next/previous buttons
        self.ui.next_frame.clicked.connect(lambda: self.set_slider(+1))
        self.ui.prev_frame.clicked.connect(lambda: self.set_slider(-1))

        #setup main slider
        self.ui.main_slider_value.valueChanged.connect(
            self.main_slider_value_changed)
        self.ui.main_slider_value.setMaximum(len(self.raw_frames) - 1)

        #setup IW/overlap size input boxes
        self.ui.iw_small_size.valueChanged.connect(self.set_small_iw_size)
        self.ui.iw_big_size.valueChanged.connect(self.set_big_iw_size)
        self.ui.iw_overlap_size.valueChanged.connect(self.set_iw_overlap_size)

        #setup maximum values for iw sliders
        self.ui.iw_pos_x.setMaximum(
            (self.frame_size_x - self.iw_big_size_value) /
            self.iw_big_size_value)
        self.ui.iw_pos_y.setMaximum(
            (self.frame_size_y - self.iw_big_size_value) /
            self.iw_big_size_value)

        #setup iw sliders
        self.ui.iw_pos_x.valueChanged.connect(self.iw_pos_x_slider_value)
        self.ui.iw_pos_y.valueChanged.connect(self.iw_pos_y_slider_value)

        #setup redraw iws checkbox and its auxilary function
        self.ui.redraw_iws.stateChanged.connect(self.check_state)
        self.state = self.ui.redraw_iws.isChecked()

        #setup plot correlation matrix button
        self.ui.plot_corr_mat.clicked.connect(self.plot_corr_mat_btn_clicked)

        #set up the initial images on the GUI, so it would look better
        self.main_pixmap = QtGui.QPixmap(self.raw_frames[0])
        self.draw_iw_bounds(self.main_pixmap)
        self.ui.label_main.setPixmap(self.main_pixmap)
        self.display_small_iw()
        self.display_big_iw()

        #reference image for getting intensity values...
        self.main_pixmap_ref_array = scipy.misc.imread((self.raw_frames[0]))

        #update iw slider max
        self.update_iw_slider_max()

        #Sets up mouse action on main window (not tested with scaling...)
        self.ui.label_main.mousePressEvent = self.getPos

        self.corr_mat_plt = None

    #######################
    #GUI specific functions
    #######################

    def getPos(self, event):
        """Prints the position of the mouse click and corresponding intensity value on the main image. The print out happens in the console"""
        x = event.pos().x()
        y = event.pos().y()
        c = self.main_pixmap_ref_array[y][x]
        print 'x,y,int =', x, y, c

    def set_slider(self, delta):
        """Changes the main frame slider by singleStep value when next/prev buttons are clicked."""
        self.ui.main_slider_value.setValue(
            self.ui.main_slider_value.value() +
            delta * self.ui.main_slider_value.singleStep())

    def update_iw_slider_max(self):
        """Enables the sliders to be 'draged by mouse' and to match the IW positions."""
        #It seems that there is no nice and simple way to be able to use "mouse sliding" of sliders so that the values would not move at arbitrary points, but to exact IW positions. One workaround is to set the maximum value of the slider to the one divided by the big IW size. However, we must take into account that we might have an overlap. This means quite a long expression, but the code could probably be cleaned up a bit by setting the "self.iw_big_size_value - self.overlap_size_value" to a single instance variable at init. It gets particularly messy in display_small/big_iw functions...
        self.ui.iw_pos_x.setMaximum(
            (scipy.misc.imread(self.raw_frames[0]).shape[1] -
             self.iw_big_size_value) /
            (self.iw_big_size_value - self.overlap_size_value))
        self.ui.iw_pos_y.setMaximum(
            (scipy.misc.imread(self.raw_frames[0]).shape[0] -
             self.iw_big_size_value) /
            (self.iw_big_size_value - self.overlap_size_value))

    def update_overlap_max(self):
        """Updates the big IW overlap size."""
        #We should not allow the overlap value to exceed the big IW value, as that will result in an error
        self.ui.iw_overlap_size.setMaximum(self.iw_big_size_value - 1)

    def update_subwindow_inset(self):
        """Updates the subwindow inset"""
        self.subwindow_inset = (self.iw_big_size_value -
                                self.iw_small_size_value) / 2

    def set_small_iw_size(self, value):
        """Takes the input value for the small IW size from the gui and sets it as an instance variable."""
        self.iw_small_size_value = value
        #the gui should only allow integers, but just in case we have an assertion.
        assert isinstance(value, int)
        self.update_subwindow_inset()
        self.display_main_image()

    def set_big_iw_size(self, value):
        """Takes the input value for the big IW size from the gui and sets it as an instance variable."""
        self.iw_big_size_value = value
        assert isinstance(value, int)
        self.display_main_image()
        self.update_subwindow_inset()
        self.update_iw_slider_max()
        self.update_overlap_max()

    def set_iw_overlap_size(self, value):
        """Takes the input value for the big IW overlap size from the gui and sets it as an instance variable."""
        self.overlap_size_value = value
        assert isinstance(value, int)
        self.display_main_image()
        self.update_iw_slider_max()

    def iw_pos_x_slider_value(self, value):
        """Functionality triggered by moving horizontal iw slider"""
        self.iw_pos_x_value = value * (self.iw_big_size_value -
                                       self.overlap_size_value)
        assert isinstance(value, int)
        self.display_main_image()
        self.display_small_iw()
        self.display_big_iw()

    def iw_pos_y_slider_value(self, value):
        """Functionality trigerred by moving vertical iw slider"""
        self.iw_pos_y_value = value * (self.iw_big_size_value -
                                       self.overlap_size_value)
        assert isinstance(value, int)
        self.display_main_image()
        self.display_small_iw()
        self.display_big_iw()

    def main_slider_value_changed(self, new_value):
        """Gets the main slider value and draws the main image"""
        self.main_slider_value = new_value
        assert isinstance(new_value, int)
        self.display_main_image()

    def display_main_image(self):
        """Displays the main image."""
        self.main_pixmap = QtGui.QPixmap(
            self.raw_frames[self.main_slider_value])
        #Reference image updated...
        self.main_pixmap_ref_array = scipy.misc.imread(
            self.raw_frames[self.main_slider_value])
        #Draws IW bounds
        self.draw_iw_bounds(self.main_pixmap)
        ####TODO: scale the whole thing. see http://stackoverflow.com/questions/24106903/resizing-qpixmap-while-maintaining-aspect-ratio, http://stackoverflow.com/questions/21041941/how-to-autoresize-qlabel-pixmap-keeping-ratio-without-using-classes
        ####TODO: enable zooming
        self.ui.label_main.setPixmap(self.main_pixmap)
        #Updates the IW images if necessary.
        self.replot_iws()

    def draw_iw_bounds(self, main_pixmap):
        """Draws the rectangles of IW window sizes on the main image. The centre is indicated by a green dot."""

        draw = QtGui.QPainter(self.main_pixmap)
        draw.setBrush(QtCore.Qt.NoBrush)
        draw.setPen(QtCore.Qt.blue)
        #Draw the small IW centered on the big IW.drawRect takes (x,y, width, height). Check what happens if the value is NOT divisible by 2.
        draw.drawRect(
            self.iw_pos_x_value +
            (self.iw_big_size_value - self.iw_small_size_value) / 2,
            self.iw_pos_y_value +
            (self.iw_big_size_value - self.iw_small_size_value) / 2,
            self.iw_small_size_value, self.iw_small_size_value)
        draw.setPen(QtCore.Qt.red)
        #Draw the big IW
        draw.drawRect(self.iw_pos_x_value, self.iw_pos_y_value,
                      self.iw_big_size_value, self.iw_big_size_value)
        draw.setPen(QtCore.Qt.green)
        #Draw a point in the centre of the two IWs.
        draw.drawPoint(self.iw_big_size_value / 2 + self.iw_pos_x_value,
                       self.iw_big_size_value / 2 + self.iw_pos_y_value)

    def display_small_iw(self):
        """Displays the small IW. Uses an extension of moving_window_array function from openpiv.The frame from which small_IWs are obtained are called frame_a or "first" frame, since we assume positive time change and frame_a is compared to frame_b. So in positive time change, and appropriate flow conditions, the big_iw should preserve the information from small_iw, hence minimising in-plane information loss."""

        frame_a = scipy.misc.imread(self.raw_frames[self.main_slider_value])
        self.small_windows = self.moving_sub_window_array(
            frame_a, self.iw_big_size_value, self.overlap_size_value,
            self.subwindow_inset)

        #field shape provides the information how many big IWs fit in the frame of interest.
        self.field_shape = openpiv.process.get_field_shape(
            image_size=scipy.misc.imread(
                self.raw_frames[self.main_slider_value]).shape,
            window_size=self.iw_big_size_value,
            overlap=self.overlap_size_value)

        ###TODO: try and make this more readable. Automate scaling?
        self.pixmap_small_iw = QtGui.QPixmap.fromImage(
            ImageQt.ImageQt(
                scipy.misc.toimage(self.small_windows[
                    self.iw_pos_x_value /
                    (self.iw_big_size_value - self.overlap_size_value) +
                    (self.iw_pos_y_value /
                     (self.iw_big_size_value - self.overlap_size_value)) *
                    self.field_shape[1]],
                                   cmax=255,
                                   cmin=0))).scaled(64, 64,
                                                    QtCore.Qt.KeepAspectRatio)
        self.ui.label_small_iw.setPixmap(self.pixmap_small_iw)

    def display_big_iw(self):
        """Displays the big IW. Uses modified moving_window_array function from openpiv.The frame from which big_IWs are obtained are called frame_b or "second" frame, since we assume positive time change and frame_a is compared to frame_b."""

        ###TODO: make sure this is consistent with openpiv correlation.
        frame_b = scipy.misc.imread(self.raw_frames[self.main_slider_value +
                                                    1])
        self.big_windows = self.moving_window_array(frame_b,
                                                    self.iw_big_size_value,
                                                    self.overlap_size_value)

        ###TODO: try and make this more readable. Automate scaling?
        self.pixmap_big_iw = QtGui.QPixmap.fromImage(
            ImageQt.ImageQt(
                scipy.misc.toimage(self.big_windows[
                    self.iw_pos_x_value /
                    (self.iw_big_size_value - self.overlap_size_value) +
                    (self.iw_pos_y_value /
                     (self.iw_big_size_value - self.overlap_size_value)) *
                    self.field_shape[1]],
                                   cmax=255,
                                   cmin=0))).scaled(128, 128,
                                                    QtCore.Qt.KeepAspectRatio)

        ###TODO: need to check if setting same cmin,cmax for the small/big IW images does give the SAME dynamic range.
        self.ui.label_big_iw.setPixmap(self.pixmap_big_iw)

    def check_state(self, state):
        """Calls replot_iws when checkbox state is changed so that IW's would get updated without changing the frame/IW position"""
        self.replot_iws()

    def replot_iws(self):
        """Sometimes it might be useful to redraw the IWs from previous frame matching, for instance, is there is a need to switch between two main frames, to see the "big picture" flow. """

        self.state = self.ui.redraw_iws.isChecked()
        if self.state == True:
            self.display_small_iw()
            self.display_big_iw()
        if self.corr_mat_plt and self.corr_mat_plt.isVisible():
            calc_cor_matrix = openpiv.process.correlate_windows(
                window_a=self.small_windows[
                    self.iw_pos_x_value /
                    (self.iw_big_size_value - self.overlap_size_value) +
                    (self.iw_pos_y_value /
                     (self.iw_big_size_value - self.overlap_size_value)) *
                    self.field_shape[1]].astype(np.float64),
                window_b=self.big_windows[
                    self.iw_pos_x_value /
                    (self.iw_big_size_value - self.overlap_size_value) +
                    (self.iw_pos_y_value /
                     (self.iw_big_size_value - self.overlap_size_value)) *
                    self.field_shape[1]].astype(np.float64),
                corr_method='fft',
                nfftx=None,
                nffty=None)
            self.corr_mat_plt.update_parameters(calc_cor_matrix)
        else:
            pass

    def plot_corr_mat_btn_clicked(self):
        """This function calls a pop up window which shows the correlation matrix"""

        self.calc_cor_matrix = openpiv.process.correlate_windows(
            window_a=self.small_windows[
                self.iw_pos_x_value /
                (self.iw_big_size_value - self.overlap_size_value) +
                (self.iw_pos_y_value /
                 (self.iw_big_size_value - self.overlap_size_value)) *
                self.field_shape[1]].astype(np.float64),
            window_b=self.big_windows[
                self.iw_pos_x_value /
                (self.iw_big_size_value - self.overlap_size_value) +
                (self.iw_pos_y_value /
                 (self.iw_big_size_value - self.overlap_size_value)) *
                self.field_shape[1]].astype(np.float64),
            corr_method='fft',
            nfftx=None,
            nffty=None)

        self.corr_mat_plt = Window(self.calc_cor_matrix.shape[0],
                                   self.calc_cor_matrix.shape[1],
                                   self.calc_cor_matrix,
                                   self.main_slider_value)

        self.corr_mat_plt.show()

    #################
    #Helper functions
    #################

    def moving_window_array(self, array, window_size, overlap):
        """Returns what the original openpiv moving_window_array function did."""
        return self.moving_sub_window_array(array, window_size, overlap, 0)

    def moving_sub_window_array(self, array, window_size, overlap,
                                subwindow_inset):
        """
        Parameters
        ----------
        array = 3D image array that we want to access in terms of its IWs

        window_size = size of each large IW

        overlap = overlap between adjacent large IWs

        subwindow_inset = the size of how far away from the boundary we push the centre of the smaller window (similar to cropping).
                            This can be set to 0 if we want to obtain the array used to access the large IW.
                            
        Written by Dr Jonathan Taylor. Based on moving_window_array function in OpenPIV (www.openpiv.net).
        """
        # The implementation of this function is rather complicated, involving the use of numpy's stride_tricks library.
        # The intention is to provide a 3D array that can be indexed using the parameters: IW index, x coord within IW, y coord within IW.
        # In order to achieve this we create a 4D array (IW x index, IW y index, ...), and flatten the first two dimensions into one.
        # Creating a 4D array like this is "relatively" easy using stride_tricks in the case where the first IW starts at (0,0).
        # However, things get a little harder if we want to create an array of small IWs, since these are inset and hence do not start at (0,0).
        # They start at (subwindow_inset, subwindow_inset). In order to achieve that we actually need to create a *fifth* dimension to
        # our intermediate array, with a stride that takes us from (0,0) to the correct starting point. We then pick out the second
        # array element in that dimension, which gives us what we want.
        sz = array.itemsize
        shape = array.shape
        subwindow_size = window_size - 2 * subwindow_inset
        assert (subwindow_size > 0)
        strides = (sz * (shape[1] * subwindow_inset + subwindow_inset),
                   sz * shape[1] * (window_size - overlap),
                   sz * (window_size - overlap), sz * shape[1], sz)
        shape = (2, int(
            (shape[0] - window_size) / (window_size - overlap)) + 1,
                 int((shape[1] - window_size) / (window_size - overlap)) + 1,
                 subwindow_size, subwindow_size)
        return np.lib.stride_tricks.as_strided(
            array, strides=strides,
            shape=shape)[1, :, :, :, :].reshape(-1, subwindow_size,
                                                subwindow_size)