Пример #1
0
def sample_image_dribinski(n=361, origin=None):
    """
    Sample test image used in the BASEX paper Rev. Sci. Instrum. 73, 2634 (2002) 
    9x Gaussian functions of half-width 4 pixel + 1 background width 3600
      - anisotropy - ß = -1  for cosθ term
                   - ß = +2  for sinθ term
                   - ß =  0  isotropic, no angular variation
    (there are some missing negative exponents in the publication)

    Parameters
    ----------
     - n: integer (square) image width (height)
     - origin: tuple,  (row, col) center of image

    Returns
    -------
     - IM: 2D n x n numpy array image

    """
    def Gauss(r, r0, sigma2):
        return np.exp(-(r - r0)**2 / sigma2)

    def I(r, theta):  # intensity function Eq. (16)
        t0 = 7 * Gauss(r, 10, 4) * np.sin(theta)**2
        t1 = 3 * Gauss(r, 15, 4)
        t2 = 5 * Gauss(r, 20, 4) * np.cos(theta)**2

        t3 = Gauss(r, 70, 4)
        t4 = 2 * Gauss(r, 85, 4) * np.cos(theta)**2
        t5 = Gauss(r, 100, 4) * np.sin(theta)**2

        t6 = 2 * Gauss(r, 145, 4) * np.sin(theta)**2
        t7 = Gauss(r, 150, 4)
        t8 = 3 * Gauss(r, 155, 4) * np.cos(theta)**2

        t9 = 20 * Gauss(r, 45, 3600)  # background under t3 to t5

        return 2000 * (t0 + t1 + t2) + 200 * (t3 + t4 + t5) + 50 * (t6 + t7 +
                                                                    t8) + t9

    # meshgrid @DanHickstein issue #67

    x = np.arange(n)
    n2 = n // 2 + n % 2
    X, Y = np.meshgrid(x - n2, x - n2)
    R, THETA = cart2polar(X, Y)
    IM = I(R, THETA)

    return IM
Пример #2
0
def sample_image_dribinski(n=361, origin=None):
    """
    Sample test image used in the BASEX paper Rev. Sci. Instrum. 73, 2634 (2002) 
    9x Gaussian functions of half-width 4 pixel + 1 background width 3600
      - anisotropy - ß = -1  for cosθ term
                   - ß = +2  for sinθ term
                   - ß =  0  isotropic, no angular variation
    (there are some missing negative exponents in the publication)

    Parameters
    ----------
     - n: integer (square) image width (height)
     - origin: tuple,  (row, col) center of image

    Returns
    -------
     - IM: 2D n x n numpy array image

    """

    def Gauss (r, r0, sigma2):
        return np.exp(-(r-r0)**2/sigma2)

    def I(r, theta):  # intensity function Eq. (16)
        t0 = 7*Gauss(r, 10, 4)*np.sin(theta)**2
        t1 = 3*Gauss(r, 15, 4)
        t2 = 5*Gauss(r, 20, 4)*np.cos(theta)**2
    
        t3 =   Gauss(r, 70, 4)
        t4 = 2*Gauss(r, 85, 4)*np.cos(theta)**2
        t5 =   Gauss(r, 100, 4)*np.sin(theta)**2

        t6 = 2*Gauss(r, 145, 4)*np.sin(theta)**2
        t7 =   Gauss(r, 150, 4)
        t8 = 3*Gauss(r, 155, 4)*np.cos(theta)**2

        t9 = 20*Gauss(r, 45, 3600)  # background under t3 to t5
    
        return 2000*(t0+t1+t2) + 200*(t3+t4+t5) + 50*(t6+t7+t8) + t9

    # meshgrid @DanHickstein issue #67

    x = np.arange(n)
    n2 = n//2 + n%2
    X, Y = np.meshgrid(x-n2, x-n2)
    R, THETA = cart2polar(X, Y)
    IM = I(R, THETA)

    return IM
Пример #3
0
def sample_image(n=361, name="dribinski", sigma=2, temperature=200):
    """
    Sample images, made up of Gaussian functions

    Parameters
    ----------
    n : integer
        image size n rows x n cols

    name : str
        one of "dribinski" or "Ominus"

    sigma : float
        Gaussian 1/e width (pixels)

    temperature : float
        for 'Ominus' only
        anion levels have Boltzmann population weight
        (2J+1) exp(-177.1 h c 100/k/temperature)

    Returns
    -------
    IM : 2D np.array
        image
    """

    def gauss(r, r0, sigma):
        return np.exp(-(r-r0)**2/sigma**2)

    def dribinski(r, theta, sigma):  # intensity function Eq. (16)
        """
        Sample test image used in the BASEX paper
        Rev. Sci. Instrum. 73, 2634 (2002)

        9x Gaussian functions of half-width 4 pixel + 1 background width 3600
        anisotropy - ß = -1  for cosθ term
                   - ß = +2  for sinθ term
                   - ß =  0  isotropic, no angular variation
        (there are some missing negative exponents in the publication)
        """

        sinetheta2 = np.sin(theta)**2
        cosinetheta2 = np.cos(theta)**2

        t0 = 7*gauss(r, 10, sigma)*sinetheta2
        t1 = 3*gauss(r, 15, sigma)
        t2 = 5*gauss(r, 20, sigma)*cosinetheta2
        t3 = gauss(r, 70, sigma)
        t4 = 2*gauss(r, 85, sigma)*cosinetheta2
        t5 = gauss(r, 100, sigma)*sinetheta2
        t6 = 2*gauss(r, 145, sigma)*sinetheta2
        t7 = gauss(r, 150, sigma)
        t8 = 3*gauss(r, 155, sigma)*cosinetheta2
        t9 = 20*gauss(r, 45, 3600)  # background under t3 to t5
        return 2000*(t0+t1+t2) + 200*(t3+t4+t5) + 50*(t6+t7+t8) + t9

    def Ominus(r, theta, sigma, boltzmann, rfact=1):
        """
        Simulate the photoelectron spectrum of O- photodetachment
        3PJ <- 2P3/2,1/2

        6 transitions, triplet neutral, and doublet anion

        """
        # positions based on 812.5 nm ANU O- PES
        t1 = gauss(r, 341*rfact, sigma)  # 3P2 <- 2P3/2
        t2 = gauss(r, 285*rfact, sigma)  # 3P1 <- 2P3/2
        t3 = gauss(r, 257*rfact, sigma)  # 3P0 <- 2P3/2
        t4 = gauss(r, 394*rfact, sigma)  # 3P2 <- 2P1/2
        t5 = gauss(r, 348*rfact, sigma)  # 3P1 <- 2P1/2
        t6 = gauss(r, 324*rfact, sigma)  # 3P0 <- 2P1/2

        # intensities = fine-structure known ratios
        # 2P1/2 transtions scaled by temperature dependent Boltzmann factor
        t = t1 + 0.8*t2 + 0.36*t3 + (0.2*t4 + 0.36*t5 + 0.16*t6)*boltzmann

        # anisotropy
        sinetheta2 = np.sin(theta)**2*0.2 + 0.8

        return t*sinetheta2

    n2 = n//2

    
    x = np.linspace(-n2, n2, n)
    
    if name=='dribinski': 
        x = x * 180/n2
    elif name=='Ominus':
        x = x * 501/n2
    

    X, Y = np.meshgrid(x, x)
    R, THETA = cart2polar(X, Y)
    if name == "dribinski":
        IM = dribinski(R, THETA, sigma=sigma)
    elif name == "Ominus":
        boltzmann = 0.5*np.exp(-177.1*const.h*const.c*100/const.k/temperature)
        IM = Ominus(R, THETA, sigma=sigma, boltzmann=boltzmann)
    else:
        raise ValueError('sample image name not recognized')

    return IM
Пример #4
0
def reproject_image_into_polar(data,
                               origin=None,
                               Jacobian=False,
                               dr=1,
                               dt=None,
                               log=False):
    """
    Reprojects a 2D numpy array (``data``) into a polar coordinate system.
    "origin" is a tuple of (x0, y0) relative to the bottom-left image corner,
    and defaults to the center of the image.
    Parameters
    ----------
    data : 2D np.array
    origin : tuple
        The coordinate of the image center, relative to bottom-left
    Jacobian : boolean
        Include ``r`` intensity scaling in the coordinate transform.
        This should be included to account for the changing pixel size that
        occurs during the transform.
    dr : float
        Radial coordinate spacing for the grid interpolation
        tests show that there is not much point in going below 0.5
    dt : float
        Angular coordinate spacing (in radians)
        if ``dt=None``, dt will be set such that the number of theta values
        is equal to the maximum value between the height or the width of
        the image.
    Returns
    -------
    output : 2D np.array
        The polar image (r, theta)
    r_grid : 2D np.array
        meshgrid of radial coordinates
    theta_grid : 2D np.array
        meshgrid of theta coordinates
    Notes
    -----
    Adapted from:
    http://stackoverflow.com/questions/3798333/image-information-along-a-polar-coordinate-system
    """
    # bottom-left coordinate system requires numpy image to be np.flipud
    data = np.flipud(data)

    ny, nx = data.shape[:2]
    if origin is None:
        origin = (nx // 2, ny // 2)

    # Determine that the min and max r and theta coords will be...
    x, y = index_coords(data, origin=origin)  # (x,y) coordinates of each pixel
    r, theta = cart2polar(x, y)  # convert (x,y) -> (r,θ), note θ=0 is vertical

    nr = np.int(np.ceil((r.max() - r.min()) / dr))

    if dt is None:
        nt = max(nx, ny)
    else:
        # dt in radians
        nt = np.int(np.ceil((theta.max() - theta.min()) / dt))

    # Make a regular (in polar space) grid based on the min and max r & theta
    if log:
        r_i = np.logspace(np.log10(r.min() + 1),
                          np.log10(r.max()),
                          nr,
                          endpoint=False)
    else:
        r_i = np.linspace(r.min(), r.max(), nr, endpoint=False)
    theta_i = np.linspace(theta.min(), theta.max(), nt, endpoint=False)
    theta_grid, r_grid = np.meshgrid(theta_i, r_i)

    # Project the r and theta grid back into pixel coordinates
    X, Y = polar2cart(r_grid, theta_grid)

    X += origin[0]  # We need to shift the origin
    Y += origin[1]  # back to the bottom-left corner...
    xi, yi = X.flatten(), Y.flatten()
    coords = np.vstack((yi, xi))  # (map_coordinates requires a 2xn array)

    zi = map_coordinates(data, coords)
    output = zi.reshape((nr, nt))

    if Jacobian:
        output = output * r_i[:, np.newaxis]

    return output, r_grid, theta_grid