Exemple #1
0
    def rotate(self, angle, scale=1.0, rotation_centre=None, recentre=True,
               missing=0.0, interpolation='bicubic', interp_param=-0.5):
        """Returns a new rotated, rescaled and shifted map.
        
        Parameters
        ---------
        angle: float
           The angle to rotate the image by (radians)        
        scale: float
           A scale factor for the image, default is no scaling
        rotation_centre: tuple
           The point in the image to rotate around (Axis of rotation).
           Default: Centre of the array
        recentre: bool, or array-like
           Move the centroid (axis of rotation) to the centre of the array
           or recentre coords. 
           Default: True, recentre to the centre of the array.
        missing: float
           The numerical value to fill any missing points after rotation.
           Default: 0.0
        interpolation: {'nearest' | 'bilinear' | 'spline' | 'bicubic'}
            Interpolation method to use in the transform. 
            Spline uses the 
            scipy.ndimage.interpolation.affline_transform routine.
            nearest, bilinear and bicubic all replicate the IDL rot() function.
            Default: 'bicubic'
        interp_par: Int or Float
            Optional parameter for controlling the interpolation.
            Spline interpolation requires an integer value between 1 and 5 for 
            the degree of the spline fit.
            Default: 3
            BiCubic interpolation requires a flaot value between -1 and 0.
            Default: 0.5
            Other interpolation options ingore the argument.
        
        Returns
        -------
        New rotated, rescaled, translated map
        """
        
        #Interpolation parameter Sanity
        assert interpolation in ['nearest','spline','bilinear','bicubic']
        #Set defaults based on interpolation
        if interp_param is None:
            if interpolation is 'spline':
                interp_param = 3
            elif interpolation is 'bicubic':
                interp_param = 0.5
            else:
                interp_param = 0 #Default value for nearest or bilinear
        
        #Make sure recenter is a vector with shape (2,1)
        if not isinstance(recentre, bool):
            recentre = np.array(recentre).reshape(2,1)
                
        #Define Size and centre of array
        centre = (np.array(self.shape)-1)/2.0
        
        #If rotation_centre is not set (None or False),
        #set rotation_centre to the centre of the image.
        if rotation_centre is None:
            rotation_centre = centre 
        else:
            #Else check rotation_centre is a vector with shape (2,1)
            rotation_centre = np.array(rotation_centre).reshape(2,1)

        #Recentre to the rotation_centre if recentre is True
        if isinstance(recentre, bool):
            #if rentre is False then this will be (0,0)
            shift = np.array(rotation_centre) - np.array(centre) 
        else:
            #Recentre to recentre vector otherwise
            shift = np.array(recentre) - np.array(centre)
        
        image = np.asarray(self).copy()
    
        #Calulate the parameters for the affline_transform
        c = np.cos(angle)
        s = np.sin(angle)
        mati = np.array([[c, s],[-s, c]]) / scale   # res->orig
        centre = np.array([centre]).transpose()  # the centre of rotn
        shift = np.array([shift]).transpose()    # the shift
        kpos = centre - np.dot(mati, (centre + shift))  
        # kpos and mati are the two transform constants, kpos is a 2x2 array
        rsmat, offs =  mati, np.squeeze((kpos[0,0], kpos[1,0]))
        
        if interpolation == 'spline':
            # This is the scipy call
            data = scipy.ndimage.interpolation.affine_transform(image, rsmat,
                           offset=offs, order=interp_param, mode='constant',
                           cval=missing)
        else:
            #Use C extension Package
            if not 'Crotate' in globals():
                raise ValueError("You do not have the C extension sunpy.image.Crotate")
            #Set up call parameters depending on interp type.
            if interpolation == 'nearest':
                interp_type = Crotate.NEAREST
            elif interpolation == 'bilinear':
                interp_type = Crotate.BILINEAR
            elif interpolation == 'bicubic':
                interp_type = Crotate.BICUBIC
            #Make call to extension
            data = Crotate.affine_transform(image, 
                                      rsmat, offset=offs, 
                                      kernel=interp_type, cubic=interp_param, 
                                      mode='constant', cval=missing)
            
        #Return a new map
        #Copy Header
        header = self._original_header.copy()
        # Create new map instance
        new_map = self.__class__(data, header)
        
        return new_map
Exemple #2
0
    print "c code"
    print timeit.timeit("out_arr = Crotate.affine_transform(in_arr, rsmat, offset=offs, kernel=Crotate.BICUBIC, cubic=int_param, mode='constant', cval=missing)",
                        setup="from __main__ import *", number=100) /100.
                        
    print "cython wrapper"
    print timeit.timeit("out_arr = aff_cythonwrap(in_arr, rsmat, offs, int_method, int_param, missing)",
                        setup="from __main__ import *", number=100) /100.
    print "cython"
    print timeit.timeit("out_arr = aff(in_arr, rsmat, offs, int_param, missing)",
                  setup="from __main__ import *", number=100) /100.
    
#    print "python"
#    print timeit.timeit("out_arr = aff_py(in_arr, rsmat, offs, int_method, int_param, missing)",
#                  setup="from __main__ import *", number=1) /1.
#              


out_arr_C = Crotate.affine_transform(in_arr, rsmat, offset=offs, kernel=Crotate.BICUBIC, cubic=int_param, mode='constant', cval=missing)   
out_arr_wr = aff_cythonwrap(in_arr, rsmat, offs, int_param, missing)
fig, ax = plt.subplots(1,3)
im1 = ax[0].imshow(out_arr_C - out_arr_wr, cmap=plt.get_cmap('Reds'), interpolation='none')
plt.colorbar(im1,ax=ax[0])
im2 = ax[1].imshow(out_arr_C, vmax =1, vmin=0, cmap=plt.get_cmap('Reds'), interpolation='none')
plt.colorbar(im2,ax=ax[1])
im3 = ax[2].imshow(out_arr_wr, vmax =1, vmin=0, cmap=plt.get_cmap('Reds'), interpolation='none')
plt.colorbar(im3,ax=ax[2])
plt.show()
#plt.imshow(out_arr)
#plt.show()
Exemple #3
0
    def rotate(
        self,
        angle=None,
        rmatrix=None,
        scale=1.0,
        rotation_center=None,
        recenter=True,
        missing=0.0,
        interpolation="bicubic",
        interp_param=-0.5,
    ):
        """Returns a new rotated, rescaled and shifted map.

        Parameters
        ----------
        angle: float
           The angle to rotate the image by (radians). Specify angle or matrix.
        rmatrix: NxN
            Linear transformation rotation matrix. Specify angle or matrix.
        scale: float
           A scale factor for the image, default is no scaling
        rotation_center: tuple
           The point in the image to rotate around (Axis of rotation).
           Default: center of the array
        recenter: bool, or array-like
           Move the centroid (axis of rotation) to the center of the array
           or recenter coords.
           Default: True, recenter to the center of the array.
        missing: float
           The numerical value to fill any missing points after rotation.
           Default: 0.0
        interpolation: {'nearest' | 'bilinear' | 'spline' | 'bicubic'}
            Interpolation method to use in the transform.
            Spline uses the
            scipy.ndimage.interpolation.affline_transform routine.
            nearest, bilinear and bicubic all replicate the IDL rot() function.
            Default: 'bicubic'
        interp_par: Int or Float
            Optional parameter for controlling the interpolation.
            Spline interpolation requires an integer value between 1 and 5 for
            the degree of the spline fit.
            Default: 3
            BiCubic interpolation requires a flaot value between -1 and 0.
            Default: 0.5
            Other interpolation options ingore the argument.

        Returns
        -------
        New rotated, rescaled, translated map

        Notes
        -----
        Apart from interpolation='spline' all other options use a compiled
        C-API extension. If for some reason this is not compiled correctly this
        routine will fall back upon the scipy implementation of order = 3.
        For more infomation see:
        http://sunpy.readthedocs.org/en/latest/guide/troubleshooting.html#crotate-warning
        """
        assert angle is None or rmatrix is None
        # Interpolation parameter Sanity
        assert interpolation in ["nearest", "spline", "bilinear", "bicubic"]
        # Set defaults based on interpolation
        if interp_param is None:
            if interpolation is "spline":
                interp_param = 3
            elif interpolation is "bicubic":
                interp_param = 0.5
            else:
                interp_param = 0  # Default value for nearest or bilinear

        # Make sure recenter is a vector with shape (2,1)
        if not isinstance(recenter, bool):
            recenter = np.array(recenter).reshape(2, 1)

        # Define Size and center of array
        center = (np.array(self.data.shape) - 1) / 2.0

        # If rotation_center is not set (None or False),
        # set rotation_center to the center of the image.
        if rotation_center is None:
            rotation_center = center
        else:
            # Else check rotation_center is a vector with shape (2,1)
            rotation_center = np.array(rotation_center).reshape(2, 1)

        # recenter to the rotation_center if recenter is True
        if isinstance(recenter, bool):
            # if rentre is False then this will be (0,0)
            shift = np.array(rotation_center) - np.array(center)
        else:
            # recenter to recenter vector otherwise
            shift = np.array(recenter) - np.array(center)

        image = self.data.copy()

        if not angle is None:
            # Calulate the parameters for the affline_transform
            c = np.cos(angle)
            s = np.sin(angle)
            mati = np.array([[c, s], [-s, c]]) / scale  # res->orig
        if not rmatrix is None:
            mati = rmatrix / scale  # res->orig
        center = np.array([center]).transpose()  # the center of rotn
        shift = np.array([shift]).transpose()  # the shift
        kpos = center - np.dot(mati, (center + shift))
        # kpos and mati are the two transform constants, kpos is a 2x2 array
        rsmat, offs = mati, np.squeeze((kpos[0, 0], kpos[1, 0]))

        if interpolation == "spline":
            # This is the scipy call
            data = scipy.ndimage.interpolation.affine_transform(
                image, rsmat, offset=offs, order=interp_param, mode="constant", cval=missing
            )
        else:
            # Use C extension Package
            if not "Crotate" in globals():
                warnings.warn(
                    """The C extension sunpy.image.Crotate is not
installed, falling back to the interpolation='spline' of order=3""",
                    Warning,
                )
                data = scipy.ndimage.interpolation.affine_transform(
                    image, rsmat, offset=offs, order=3, mode="constant", cval=missing
                )
            else:
                # Set up call parameters depending on interp type.
                if interpolation == "nearest":
                    interp_type = Crotate.NEAREST
                elif interpolation == "bilinear":
                    interp_type = Crotate.BILINEAR
                elif interpolation == "bicubic":
                    interp_type = Crotate.BICUBIC
                # Make call to extension
                data = Crotate.affine_transform(
                    image, rsmat, offset=offs, kernel=interp_type, cubic=interp_param, mode="constant", cval=missing
                )

        # Return a new map
        # Copy Header
        new_map = deepcopy(self)

        # Create new map instance
        new_map.data = data
        return new_map
Exemple #4
0
    def rotate(self,
               angle=None,
               rmatrix=None,
               scale=1.0,
               rotation_center=None,
               recenter=True,
               missing=0.0,
               interpolation='bicubic',
               interp_param=-0.5):
        """Returns a new rotated, rescaled and shifted map.

        Parameters
        ----------
        angle: float
           The angle to rotate the image by (radians). Specify angle or matrix.
        rmatrix: NxN
            Linear transformation rotation matrix. Specify angle or matrix.
        scale: float
           A scale factor for the image, default is no scaling
        rotation_center: tuple
           The point in the image to rotate around (Axis of rotation).
           Default: center of the array
        recenter: bool, or array-like
           Move the centroid (axis of rotation) to the center of the array
           or recenter coords.
           Default: True, recenter to the center of the array.
        missing: float
           The numerical value to fill any missing points after rotation.
           Default: 0.0
        interpolation: {'nearest' | 'bilinear' | 'spline' | 'bicubic'}
            Interpolation method to use in the transform.
            Spline uses the
            scipy.ndimage.interpolation.affline_transform routine.
            nearest, bilinear and bicubic all replicate the IDL rot() function.
            Default: 'bicubic'
        interp_par: Int or Float
            Optional parameter for controlling the interpolation.
            Spline interpolation requires an integer value between 1 and 5 for
            the degree of the spline fit.
            Default: 3
            BiCubic interpolation requires a flaot value between -1 and 0.
            Default: 0.5
            Other interpolation options ingore the argument.

        Returns
        -------
        New rotated, rescaled, translated map

        Notes
        -----
        Apart from interpolation='spline' all other options use a compiled
        C-API extension. If for some reason this is not compiled correctly this
        routine will fall back upon the scipy implementation of order = 3.
        For more infomation see:
        http://sunpy.readthedocs.org/en/latest/guide/troubleshooting.html#crotate-warning
        """
        assert angle is None or rmatrix is None
        #Interpolation parameter Sanity
        assert interpolation in ['nearest', 'spline', 'bilinear', 'bicubic']
        #Set defaults based on interpolation
        if interp_param is None:
            if interpolation is 'spline':
                interp_param = 3
            elif interpolation is 'bicubic':
                interp_param = 0.5
            else:
                interp_param = 0  #Default value for nearest or bilinear

        #Make sure recenter is a vector with shape (2,1)
        if not isinstance(recenter, bool):
            recenter = np.array(recenter).reshape(2, 1)

        #Define Size and center of array
        center = (np.array(self.data.shape) - 1) / 2.0

        #If rotation_center is not set (None or False),
        #set rotation_center to the center of the image.
        if rotation_center is None:
            rotation_center = center
        else:
            #Else check rotation_center is a vector with shape (2,1)
            rotation_center = np.array(rotation_center).reshape(2, 1)

        #recenter to the rotation_center if recenter is True
        if isinstance(recenter, bool):
            #if rentre is False then this will be (0,0)
            shift = np.array(rotation_center) - np.array(center)
        else:
            #recenter to recenter vector otherwise
            shift = np.array(recenter) - np.array(center)

        image = self.data.copy()

        if not angle is None:
            #Calulate the parameters for the affline_transform
            c = np.cos(angle)
            s = np.sin(angle)
            mati = np.array([[c, s], [-s, c]]) / scale  # res->orig
        if not rmatrix is None:
            mati = rmatrix / scale  # res->orig
        center = np.array([center]).transpose()  # the center of rotn
        shift = np.array([shift]).transpose()  # the shift
        kpos = center - np.dot(mati, (center + shift))
        # kpos and mati are the two transform constants, kpos is a 2x2 array
        rsmat, offs = mati, np.squeeze((kpos[0, 0], kpos[1, 0]))

        if interpolation == 'spline':
            # This is the scipy call
            data = scipy.ndimage.interpolation.affine_transform(
                image,
                rsmat,
                offset=offs,
                order=interp_param,
                mode='constant',
                cval=missing)
        else:
            #Use C extension Package
            if not 'Crotate' in globals():
                warnings.warn(
                    """The C extension sunpy.image.Crotate is not
installed, falling back to the interpolation='spline' of order=3""", Warning)
                data = scipy.ndimage.interpolation.affine_transform(
                    image,
                    rsmat,
                    offset=offs,
                    order=3,
                    mode='constant',
                    cval=missing)
            else:
                #Set up call parameters depending on interp type.
                if interpolation == 'nearest':
                    interp_type = Crotate.NEAREST
                elif interpolation == 'bilinear':
                    interp_type = Crotate.BILINEAR
                elif interpolation == 'bicubic':
                    interp_type = Crotate.BICUBIC
                #Make call to extension
                data = Crotate.affine_transform(image,
                                                rsmat,
                                                offset=offs,
                                                kernel=interp_type,
                                                cubic=interp_param,
                                                mode='constant',
                                                cval=missing)

        #Return a new map
        #Copy Header
        new_map = deepcopy(self)

        # Create new map instance
        new_map.data = data
        return new_map
Exemple #5
0
    def rotate(self, angle=None, rmatrix=None, scale=1.0,
               rotation_center=(0, 0), recenter=False,
               missing=0.0, interpolation='bicubic', interp_param=-0.5):
        """Returns a new rotated and rescaled map.  Specify either a rotation
        angle or a rotation matrix, but not both.  If neither an angle or a
        rotation matrix are specified, the map will be rotated by the rotation
        angle in the metadata.

        If the rotation is specified as an angle (either explicitly or
        implicitly) and the metadata contains the CROTA2 keyword, that keyword
        will be changed appropriately to account for the rotation.

        Parameters
        ----------
        angle: float
            The angle (degrees) to rotate counterclockwise.
        rmatrix: NxN
            Linear transformation rotation matrix.
        scale: float
            A scale factor for the image, default is no scaling
        rotation_center: tuple
            The axis of rotation
            Default: the origin in the data coordinate system
        recenter: bool
            If True, position the axis of rotation at the center of the new map
            Default: False
        missing: float
            The numerical value to fill any missing points after rotation.
            Default: 0.0
        interpolation: {'nearest' | 'bilinear' | 'spline' | 'bicubic'}
            Interpolation method to use in the transform.
            Spline uses the
            scipy.ndimage.interpolation.affline_transform routine.
            nearest, bilinear and bicubic all replicate the IDL rot() function.
            Default: 'bicubic'
        interp_par: Int or Float
            Optional parameter for controlling the interpolation.
            Spline interpolation requires an integer value between 1 and 5 for
            the degree of the spline fit.
            Default: 3
            BiCubic interpolation requires a flaot value between -1 and 0.
            Default: 0.5
            Other interpolation options ingore the argument.

        Returns
        -------
        New rotated and rescaled map

        Notes
        -----
        Apart from interpolation='spline' all other options use a compiled
        C-API extension. If for some reason this is not compiled correctly this
        routine will fall back upon the scipy implementation of order = 3.
        For more infomation see:
        http://sunpy.readthedocs.org/en/latest/guide/troubleshooting.html#crotate-warning
        """
        assert angle is None or rmatrix is None
        # Interpolation parameter sanity
        assert interpolation in ['nearest', 'spline', 'bilinear', 'bicubic']
        # Set defaults based on interpolation
        if interp_param is None:
            if interpolation is 'spline':
                interp_param = 3
            elif interpolation is 'bicubic':
                interp_param = 0.5
            else:
                interp_param = 0 # Default value for nearest or bilinear

        image = self.data.copy()

        if angle is None and rmatrix is None:
            angle = self.rotation_angle['y']

        if not angle is None:
            #Calulate the parameters for the affine_transform
            c = np.cos(np.deg2rad(angle))
            s = np.sin(np.deg2rad(angle))
            rsmat = np.array([[c, -s], [s, c]]) / scale
        if not rmatrix is None:
            rsmat = np.asarray(rmatrix) / scale

        # map_center is swapped compared to the x-y convention
        map_center = (np.array(self.data.shape)-1)/2.0

        # axis is swapped compared to the x-y convention
        if recenter:
            axis_x = self.data_to_pixel(rotation_center[0], 'x')
            axis_y = self.data_to_pixel(rotation_center[1], 'y')
            axis = (axis_y, axis_x)
        else:
            axis = map_center

        # offs is swapped compared to the x-y convention
        offs = axis - np.dot(rsmat, map_center)

        if interpolation == 'spline':
            # This is the scipy call
            data = interp.affine_transform(image, rsmat, offset=offs,
                                           order=interp_param, mode='constant',
                                           cval=missing)
        else:
            #Use C extension Package
            if not 'Crotate' in globals():
                warnings.warn("""The C extension sunpy.image.Crotate is not
installed, falling back to the interpolation='spline' of order=3""" ,Warning)
                data = interp.affine_transform(image, rsmat, offset=offs,
                                               order=3, mode='constant',
                                               cval=missing)
            else:
                #Set up call parameters depending on interp type.
                if interpolation == 'nearest':
                    interp_type = Crotate.NEAREST
                elif interpolation == 'bilinear':
                    interp_type = Crotate.BILINEAR
                elif interpolation == 'bicubic':
                    interp_type = Crotate.BICUBIC
                #Make call to extension
                data = Crotate.affine_transform(image,
                                                rsmat, offset=offs,
                                                kernel=interp_type,
                                                cubic=interp_param,
                                                mode='constant',
                                                cval=missing)

        #Return a new map
        #Copy Header
        new_map = deepcopy(self)

        # Create new map instance
        new_map.data = data

        if recenter:
            new_center = rotation_center
        else:
            # Retrieve old coordinates for the center of the array
            old_center = np.array(new_map.pixel_to_data(map_center[1], map_center[0]))

            # Calculate new coordinates for the center of the array
            new_center = rotation_center - np.dot(rsmat, rotation_center - old_center)

        # Define a new reference pixel in the rotated space
        new_map.meta['crval1'] = new_center[0]
        new_map.meta['crval2'] = new_center[1]
        new_map.meta['crpix1'] = map_center[1] + 1 # FITS counts pixels from 1
        new_map.meta['crpix2'] = map_center[0] + 1 # FITS counts pixels from 1

        if angle is not None and new_map.meta.get('crota2') is not None:
            new_map.meta['crota2'] = new_map.rotation_angle['y'] - angle

        return new_map
Exemple #6
0
    def rotate(self,
               angle=None,
               rmatrix=None,
               scale=1.0,
               rotation_center=(0, 0),
               recenter=False,
               missing=0.0,
               interpolation='bicubic',
               interp_param=-0.5):
        """Returns a new rotated and rescaled map.  Specify either a rotation
        angle or a rotation matrix, but not both.  If neither an angle or a
        rotation matrix are specified, the map will be rotated by the rotation
        angle in the metadata.

        If the rotation is specified as an angle (either explicitly or
        implicitly) and the metadata contains the CROTA2 keyword, that keyword
        will be changed appropriately to account for the rotation.

        Parameters
        ----------
        angle: float
            The angle (degrees) to rotate counterclockwise.
        rmatrix: NxN
            Linear transformation rotation matrix.
        scale: float
            A scale factor for the image, default is no scaling
        rotation_center: tuple
            The axis of rotation
            Default: the origin in the data coordinate system
        recenter: bool
            If True, position the axis of rotation at the center of the new map
            Default: False
        missing: float
            The numerical value to fill any missing points after rotation.
            Default: 0.0
        interpolation: {'nearest' | 'bilinear' | 'spline' | 'bicubic'}
            Interpolation method to use in the transform.
            Spline uses the
            scipy.ndimage.interpolation.affline_transform routine.
            nearest, bilinear and bicubic all replicate the IDL rot() function.
            Default: 'bicubic'
        interp_par: Int or Float
            Optional parameter for controlling the interpolation.
            Spline interpolation requires an integer value between 1 and 5 for
            the degree of the spline fit.
            Default: 3
            BiCubic interpolation requires a flaot value between -1 and 0.
            Default: 0.5
            Other interpolation options ingore the argument.

        Returns
        -------
        New rotated and rescaled map

        Notes
        -----
        Apart from interpolation='spline' all other options use a compiled
        C-API extension. If for some reason this is not compiled correctly this
        routine will fall back upon the scipy implementation of order = 3.
        For more infomation see:
        http://sunpy.readthedocs.org/en/latest/guide/troubleshooting.html#crotate-warning
        """
        assert angle is None or rmatrix is None
        # Interpolation parameter sanity
        assert interpolation in ['nearest', 'spline', 'bilinear', 'bicubic']
        # Set defaults based on interpolation
        if interp_param is None:
            if interpolation is 'spline':
                interp_param = 3
            elif interpolation is 'bicubic':
                interp_param = 0.5
            else:
                interp_param = 0  # Default value for nearest or bilinear

        image = self.data.copy()

        if angle is None and rmatrix is None:
            angle = self.rotation_angle['y']

        if not angle is None:
            #Calulate the parameters for the affine_transform
            c = np.cos(np.deg2rad(angle))
            s = np.sin(np.deg2rad(angle))
            rsmat = np.array([[c, -s], [s, c]]) / scale
        if not rmatrix is None:
            rsmat = np.asarray(rmatrix) / scale

        # map_center is swapped compared to the x-y convention
        map_center = (np.array(self.data.shape) - 1) / 2.0

        # axis is swapped compared to the x-y convention
        if recenter:
            axis_x = self.data_to_pixel(rotation_center[0], 'x')
            axis_y = self.data_to_pixel(rotation_center[1], 'y')
            axis = (axis_y, axis_x)
        else:
            axis = map_center

        # offs is swapped compared to the x-y convention
        offs = axis - np.dot(rsmat, map_center)

        if interpolation == 'spline':
            # This is the scipy call
            data = interp.affine_transform(image,
                                           rsmat,
                                           offset=offs,
                                           order=interp_param,
                                           mode='constant',
                                           cval=missing)
        else:
            #Use C extension Package
            if not 'Crotate' in globals():
                warnings.warn(
                    """The C extension sunpy.image.Crotate is not
installed, falling back to the interpolation='spline' of order=3""", Warning)
                data = interp.affine_transform(image,
                                               rsmat,
                                               offset=offs,
                                               order=3,
                                               mode='constant',
                                               cval=missing)
            else:
                #Set up call parameters depending on interp type.
                if interpolation == 'nearest':
                    interp_type = Crotate.NEAREST
                elif interpolation == 'bilinear':
                    interp_type = Crotate.BILINEAR
                elif interpolation == 'bicubic':
                    interp_type = Crotate.BICUBIC
                #Make call to extension
                data = Crotate.affine_transform(image,
                                                rsmat,
                                                offset=offs,
                                                kernel=interp_type,
                                                cubic=interp_param,
                                                mode='constant',
                                                cval=missing)

        #Return a new map
        #Copy Header
        new_map = deepcopy(self)

        # Create new map instance
        new_map.data = data

        if recenter:
            new_center = rotation_center
        else:
            # Retrieve old coordinates for the center of the array
            old_center = np.array(
                new_map.pixel_to_data(map_center[1], map_center[0]))

            # Calculate new coordinates for the center of the array
            new_center = rotation_center - np.dot(rsmat,
                                                  rotation_center - old_center)

        # Define a new reference pixel in the rotated space
        new_map.meta['crval1'] = new_center[0]
        new_map.meta['crval2'] = new_center[1]
        new_map.meta['crpix1'] = map_center[1] + 1  # FITS counts pixels from 1
        new_map.meta['crpix2'] = map_center[0] + 1  # FITS counts pixels from 1

        if angle is not None and new_map.meta.get('crota2') is not None:
            new_map.meta['crota2'] = new_map.rotation_angle['y'] - angle

        return new_map