Source code for tuna.tools.phase_map.find_image_center_by_symmetry

"""
This module's scope is the method of finding the image center exploiting its symmetry. Therefore its applicability is limited to highly symmetric images.

Example::

    >>> import tuna
    >>> barycenter = tuna.io.read ( "tuna/test/unit/unit_io/G094_03_wrapped_phase_map.fits" )
    >>> tuna.tools.phase_map.find_image_center_by_symmetry ( data = barycenter.array )
    (219, 256)
"""

import logging
import numpy
import time

[docs]class image_center_by_symmetry ( object ): """ This class responsibility is to find the center of an image by finding the row and the column that split the image with the highest degree of symmetry. If a cube is received, it will use the first plane as its input. Its constructor signature is: Parameters: * array : numpy.ndarray Containing the image whose center we intend to find. """ def __init__ ( self, array = numpy.ndarray ): super ( image_center_by_symmetry, self ).__init__ ( ) self.__version__ = "0.1.0" self.changelog = { "0.1.0" : "Tuna 0.14.0 : improved documentation." } self.log = logging.getLogger ( __name__ ) self.__input_array = None if array.ndim == 2: self.__input_array = array elif array.ndim == 3: self.__input_array = array[0,:,:] else: self.log ( "Incorrect ndims for input array." ) self.__center_row = None self.__center_col = None
[docs] def get_center ( self ): """ This method's goal is to access the center coordinates. Will trigger a find if the center is yet unknown. Returns: * unnamed variable : tuple of 2 integers Containing the column and row indexes for the center. """ if ( ( self.__center_row is not None ) and ( self.__center_col is not None ) ): return ( self.__center_row, self.__center_col ) else: self.find_center ( ) return ( self.__center_row, self.__center_col )
[docs] def find_center ( self ): """ This method's goal is to find the center of the image, by splitting the image into same-sized chunks, where the relative distances to the center are the same. The center will have circular symmetry, and therefore these chunks will be very similar. """ input = self.__input_array self.log.debug ( "Searching for most symmetric by-row split." ) row_results = numpy.ndarray ( shape = ( input.shape[0] ) ) row_results.fill ( numpy.inf ) sixteenth = int ( input.shape [ 0 ] / 16 ) for row in range ( sixteenth, sixteenth * 15 ): bottom = input [ row - sixteenth : row - 1, : ] top = input [ row + 1 : row + sixteenth, : ] top = top [ : : -1, : ] difference = bottom - top row_results [ row ] = numpy.sum ( numpy.abs ( difference ) ) self.log.debug ( row_results ) self.__center_row = numpy.argmin ( row_results ) self.log.debug ( "Searching for most symmetric columnar split." ) col_results = numpy.ndarray ( shape = ( input.shape[1] ) ) col_results.fill ( numpy.inf ) sixteenth = int ( input.shape [ 1 ] / 16 ) for col in range ( sixteenth, sixteenth * 15 ): left = input [ : , col - sixteenth : col - 1 ] right = input [ : , col + 1 : col + sixteenth ] right = right [ : , : : -1 ] difference = left - right col_results [ col ] = numpy.sum ( numpy.abs ( difference ) ) self.log.debug ( col_results ) self.__center_col = numpy.argmin ( col_results ) self.log.debug ( "Center near ( %d, %d )." % ( self.__center_row, self.__center_col ) )
[docs]def find_image_center_by_symmetry ( data = numpy.ndarray ): """ This function's goal is to conveniently wrap the search for the center of the input image. Parameters: * data : numpy.ndarray Should receive the data where a highly symmetric image can be found. Returns: * iit_center : tuple of 2 integers Containing the column and row of the found center. """ start = time.time ( ) log = logging.getLogger ( __name__ ) o_finder = image_center_by_symmetry ( array = data ) iit_center = o_finder.get_center ( ) log.debug ( "iit_center = %s" % str ( iit_center ) ) log.debug ( "find_image_center_by_symmetry() took %ds." % ( time.time ( ) - start ) ) return iit_center