Ejemplo n.º 1
0
def getZoneByLocation(lat, lon, level):
    level += 2
    h_size = calcHexSize(level)

    z_xy = loc2xy(lon, lat)
    lon_grid = z_xy.x
    lat_grid = z_xy.y
    unit_x = 6 * h_size
    unit_y = 6 * h_size * H_K
    h_pos_x = (lon_grid + lat_grid / H_K) / unit_x
    h_pos_y = (lat_grid - H_K * lon_grid) / unit_y
    h_x_0 = floor_int(h_pos_x)
    h_y_0 = floor_int(h_pos_y)
    h_x_q = h_pos_x - h_x_0 
    h_y_q = h_pos_y - h_y_0
    h_x = round_int(h_pos_x)
    h_y = round_int(h_pos_y)

    if h_y_q > -h_x_q + 1:
        if (h_y_q < 2 * h_x_q) and (h_y_q > 0.5 * h_x_q):
            h_x = h_x_0 + 1
            h_y = h_y_0 + 1
    elif h_y_q < -h_x_q + 1:
        if (h_y_q > (2 * h_x_q) - 1) and (h_y_q < (0.5 * h_x_q) + 0.5):
            h_x = h_x_0
            h_y = h_y_0

    h_lat = (H_K * h_x * unit_x + h_y * unit_y) / 2
    h_lon = (h_lat - h_y * unit_y) / H_K

    z_loc = xy2loc(h_lon, h_lat)
    z_loc_x = z_loc.lon
    z_loc_y = z_loc.lat
    if H_BASE - h_lon < h_size:
        z_loc_x = 180
        h_xy = h_x
        h_x = h_y
        h_y = h_xy

    h_code = ""
    code3_x = [0] * (level + 1)
    code3_y = [0] * (level + 1)
    code3 = ""
    code9 = ""
    mod_x = h_x
    mod_y = h_y

    for i in range(level + 1):
        h_pow = math.pow(3, level - i)
        if mod_x >= ceil_int(h_pow/2):
            code3_x[i] = 2
            mod_x -= h_pow
        elif mod_x <= -ceil_int(h_pow/2):
            code3_x[i] = 0
            mod_x += h_pow
        else:
            code3_x[i] = 1

        if mod_y >= ceil_int(h_pow/2):
            code3_y[i] =2
            mod_y -= h_pow
        elif mod_y <= -ceil_int(h_pow/2):
             code3_y[i] =0
             mod_y += h_pow
        else:
            code3_y[i] = 1

    for i in range(len(code3_x)):
        code3 += "%s%s" % (code3_x[i], code3_y[i])
        code9 += str(int(code3, 3))
        h_code += code9
        code9 = ""
        code3 = ""

    h_2 = h_code[3:]
    h_1 = h_code[0:3]
    h_a1 = floor_int(int(h_1) / 30)
    h_a2 = int(h_1) % 30
    h_code = (H_KEY[h_a1] + H_KEY[h_a2]) + h_2

    return Zone(z_loc_y, z_loc_x, h_x, h_y, h_code)
Ejemplo n.º 2
0
def find_bubble_edges(array, blob, max_extent=1.0,
                      edge_mask=None,
                      nsig_thresh=1, value_thresh=None,
                      radius=None, return_mask=False, min_pixels=16,
                      filter_size=4, verbose=False,
                      min_radius_frac=0.0, try_local_bkg=True,
                      **kwargs):
        '''
        Expand/contract to match the contours in the data.

        Parameters
        ----------
        array : 2D numpy.ndarray or spectral_cube.LowerDimensionalObject
            Data used to define the region boundaries.
        max_extent : float, optional
            Multiplied by the major radius to set how far should be searched
            when searching for the boundary.
        nsig_thresh : float, optional
            Number of times sigma above the mean to set the boundary intensity
            requirement. This is used whenever the local background is higher
            than the given `value_thresh`.
        value_thresh : float, optional
            When given, sets the minimum intensity for defining a bubble edge.
            The natural choice is a few times the noise level in the cube.
        radius : float, optional
            Give an optional radius to use instead of the major radius defined
            for the bubble.
        kwargs : passed to profile.profile_line.

        Returns
        -------
        extent_coords : np.ndarray
            Array with the positions of edges.
        '''

        if try_local_bkg:
            mean, std = intensity_props(array, blob)
            background_thresh = mean + nsig_thresh * std

            # Define a suitable background based on the intensity within the
            # elliptical region
            if value_thresh is None:
                value_thresh = background_thresh
            else:
                # If value_thresh is higher use it. Otherwise use the bkg.
                if value_thresh < background_thresh:
                    value_thresh = background_thresh

        # Set the number of theta to be ~ the perimeter.

        y, x, major, minor, pa = blob[:5]
        y = int(np.round(y, decimals=0))
        x = int(np.round(x, decimals=0))

        # If the center is on the edge of the array, subtract one to
        # index correctly
        if y == array.shape[0]:
            y -= 1
        if x == array.shape[1]:
            x -= 1

        # Use the ellipse model to define a bounding box for the mask.
        bbox = Ellipse2D(True, 0.0, 0.0, major * max_extent,
                         minor * max_extent, pa).bounding_box

        y_range = ceil_int(bbox[0][1] - bbox[0][0] + 1 + filter_size)
        x_range = ceil_int(bbox[1][1] - bbox[1][0] + 1 + filter_size)

        shell_thetas = []

        yy, xx = np.mgrid[-int(y_range / 2): int(y_range / 2) + 1,
                          -int(x_range / 2): int(x_range / 2) + 1]

        if edge_mask is not None:
            arr = edge_mask[max(0, y - int(y_range / 2)):
                            y + int(y_range / 2) + 1,
                            max(0, x - int(x_range / 2)):
                            x + int(x_range / 2) + 1]
        else:
            arr = array[max(0, y - int(y_range / 2)):y + int(y_range / 2) + 1,
                        max(0, x - int(x_range / 2)):x + int(x_range / 2) + 1]

        # Adjust meshes if they exceed the array shape
        x_min = -min(0, x - int(x_range / 2))
        x_max = xx.shape[1] - max(0, x + int(x_range / 2) - array.shape[1] + 1)
        y_min = -min(0, y - int(y_range / 2))
        y_max = yy.shape[0] - max(0, y + int(y_range / 2) - array.shape[0] + 1)

        offset = (max(0, int(y - (y_range / 2))),
                  max(0, int(x - (x_range / 2))))

        yy = yy[y_min:y_max, x_min:x_max]
        xx = xx[y_min:y_max, x_min:x_max]

        dist_arr = np.sqrt(yy**2 + xx**2)

        if edge_mask is not None:
            smooth_mask = arr
        else:
            smooth_mask = \
                smooth_edges(arr <= value_thresh, filter_size, min_pixels)

        region_mask = \
            Ellipse2D(True, 0.0, 0.0, major * max_extent, minor * max_extent,
                      pa)(xx, yy).astype(bool)
        region_mask = nd.binary_dilation(region_mask, eight_conn, iterations=2)

        # The bubble center must fall within a valid region
        mid_pt = np.where(dist_arr == 0.0)
        if len(mid_pt[0]) == 0:
            middle_fail = True
        else:
            local_center = zip(*np.where(dist_arr == 0.0))[0]
            middle_fail = False
        # _make_bubble_mask(smooth_mask, local_center)

        # If the center is not contained within a bubble region, return
        # empties.
        bad_case = not smooth_mask.any() or smooth_mask.all() or \
            (smooth_mask * region_mask).all() or middle_fail
        if bad_case:
            if return_mask:
                return np.array([]), 0.0, 0.0, value_thresh, smooth_mask

            return np.array([]), 0.0, 0.0, value_thresh

        orig_perim = find_contours(region_mask, 0, fully_connected='high')[0]
        # new_perim = find_contours(smooth_mask, 0, fully_connected='high')
        coords = []
        extent_mask = np.zeros_like(region_mask)
        # for perim in new_perim:
        #     perim = perim.astype(np.int)
        #     good_pts = \
        #         np.array([pos for pos, pt in enumerate(perim)
        #                   if region_mask[pt[0], pt[1]]])
        #     if not good_pts.any():
        #         continue

        #     # Now split into sections
        #     from utils import consec_split
        #     split_pts = consec_split(good_pts)

        #     # Remove the duplicated end point if it was initially connected
        #     if len(split_pts) > 1:
        #         # Join these if the end pts initially matched
        #         if split_pts[0][0] == split_pts[-1][-1]:
        #             split_pts[0] = np.append(split_pts[0],
        #                                      split_pts[-1][::-1])
        #             split_pts.pop(-1)

        #     for split in split_pts:
        #         coords.append(perim[split])

        #     extent_mask[perim[good_pts][:, 0], perim[good_pts][:, 1]] = True

        # Based on the curvature of the shell, only fit points whose
        # orientation matches the assumed centre.
        # incoord, outcoord = shell_orientation(coords, local_center,
        #                                       verbose=False)

        # Now only keep the points that are not blocked from the centre pixel
        for pt in orig_perim:

            theta = np.arctan2(pt[0] - local_center[0],
                               pt[1] - local_center[1])

            num_pts = int(np.round(np.hypot(pt[0] - local_center[0],
                                            pt[1] - local_center[1]),
                                   decimals=0))

            ys = np.round(np.linspace(local_center[0], pt[0], num_pts),
                          decimals=0).astype(np.int)

            xs = np.round(np.linspace(local_center[1], pt[1], num_pts),
                          decimals=0).astype(np.int)

            not_on_edge = np.logical_and(ys < smooth_mask.shape[0],
                                         xs < smooth_mask.shape[1])
            ys = ys[not_on_edge]
            xs = xs[not_on_edge]

            dist = np.sqrt((ys - local_center[0])**2 +
                           (xs - local_center[1])**2)

            prof = smooth_mask[ys, xs]

            prof = prof[dist >= min_radius_frac * minor]
            ys = ys[dist >= min_radius_frac * minor]
            xs = xs[dist >= min_radius_frac * minor]

            # Look for the first 0 and ignore all others past it
            zeros = np.where(prof == 0)[0]

            # If none, move on
            if not zeros.any():
                continue

            edge = zeros[0]

            extent_mask[ys[edge], xs[edge]] = True
            coords.append((ys[edge], xs[edge]))
            shell_thetas.append(theta)

        # Calculate the fraction of the region associated with a shell
        shell_frac = len(shell_thetas) / float(len(orig_perim))

        shell_thetas = np.array(shell_thetas)
        coords = np.array(coords)

        # Use the theta values to find the standard deviation i.e. how
        # dispersed the shell locations are. Assumes a circle, but we only
        # consider moderately elongated ellipses, so the statistics approx.
        # hold.
        theta_var = np.sqrt(circvar(shell_thetas * u.rad)).value

        extent_coords = \
            np.vstack([pt + off for pt, off in
                       zip(np.where(extent_mask), offset)]).T

        if verbose:
            print("Shell fraction : " + str(shell_frac))
            print("Angular Std. : " + str(theta_var))
            import matplotlib.pyplot as p
            true_region_mask = \
                Ellipse2D(True, 0.0, 0.0, major, minor,
                          pa)(xx, yy).astype(bool)

            ax = p.subplot(121)
            ax.imshow(arr, origin='lower',
                      interpolation='nearest')
            ax.contour(smooth_mask, colors='b')
            ax.contour(region_mask, colors='r')
            ax.contour(true_region_mask, colors='g')
            if len(coords) > 0:
                p.plot(coords[:, 1], coords[:, 0], 'bD')
            p.plot(local_center[1], local_center[0], 'gD')
            ax2 = p.subplot(122)
            ax2.imshow(extent_mask, origin='lower',
                       interpolation='nearest')
            p.draw()
            raw_input("?")
            p.clf()

        if return_mask:
            return extent_coords, shell_frac, theta_var, value_thresh, \
                extent_mask

        return extent_coords, shell_frac, theta_var, value_thresh
Ejemplo n.º 3
0
def find_bubble_edges(array,
                      blob,
                      max_extent=1.0,
                      edge_mask=None,
                      nsig_thresh=1,
                      value_thresh=None,
                      radius=None,
                      return_mask=False,
                      min_pixels=16,
                      filter_size=4,
                      verbose=False,
                      min_radius_frac=0.0,
                      try_local_bkg=True,
                      **kwargs):
    '''
        Expand/contract to match the contours in the data.

        Parameters
        ----------
        array : 2D numpy.ndarray or spectral_cube.LowerDimensionalObject
            Data used to define the region boundaries.
        max_extent : float, optional
            Multiplied by the major radius to set how far should be searched
            when searching for the boundary.
        nsig_thresh : float, optional
            Number of times sigma above the mean to set the boundary intensity
            requirement. This is used whenever the local background is higher
            than the given `value_thresh`.
        value_thresh : float, optional
            When given, sets the minimum intensity for defining a bubble edge.
            The natural choice is a few times the noise level in the cube.
        radius : float, optional
            Give an optional radius to use instead of the major radius defined
            for the bubble.
        kwargs : passed to profile.profile_line.

        Returns
        -------
        extent_coords : np.ndarray
            Array with the positions of edges.
        '''

    if try_local_bkg:
        mean, std = intensity_props(array, blob)
        background_thresh = mean + nsig_thresh * std

        # Define a suitable background based on the intensity within the
        # elliptical region
        if value_thresh is None:
            value_thresh = background_thresh
        else:
            # If value_thresh is higher use it. Otherwise use the bkg.
            if value_thresh < background_thresh:
                value_thresh = background_thresh

    # Set the number of theta to be ~ the perimeter.

    y, x, major, minor, pa = blob[:5]
    y = int(np.round(y, decimals=0))
    x = int(np.round(x, decimals=0))

    # If the center is on the edge of the array, subtract one to
    # index correctly
    if y == array.shape[0]:
        y -= 1
    if x == array.shape[1]:
        x -= 1

    # Use the ellipse model to define a bounding box for the mask.
    bbox = Ellipse2D(True, 0.0, 0.0, major * max_extent, minor * max_extent,
                     pa).bounding_box

    y_range = ceil_int(bbox[0][1] - bbox[0][0] + 1 + filter_size)
    x_range = ceil_int(bbox[1][1] - bbox[1][0] + 1 + filter_size)

    shell_thetas = []

    yy, xx = np.mgrid[-int(y_range / 2):int(y_range / 2) + 1,
                      -int(x_range / 2):int(x_range / 2) + 1]

    if edge_mask is not None:
        arr = edge_mask[max(0, y - int(y_range / 2)):y + int(y_range / 2) + 1,
                        max(0, x - int(x_range / 2)):x + int(x_range / 2) + 1]
    else:
        arr = array[max(0, y - int(y_range / 2)):y + int(y_range / 2) + 1,
                    max(0, x - int(x_range / 2)):x + int(x_range / 2) + 1]

    # Adjust meshes if they exceed the array shape
    x_min = -min(0, x - int(x_range / 2))
    x_max = xx.shape[1] - max(0, x + int(x_range / 2) - array.shape[1] + 1)
    y_min = -min(0, y - int(y_range / 2))
    y_max = yy.shape[0] - max(0, y + int(y_range / 2) - array.shape[0] + 1)

    offset = (max(0, int(y - (y_range / 2))), max(0, int(x - (x_range / 2))))

    yy = yy[y_min:y_max, x_min:x_max]
    xx = xx[y_min:y_max, x_min:x_max]

    dist_arr = np.sqrt(yy**2 + xx**2)

    if edge_mask is not None:
        smooth_mask = arr
    else:
        smooth_mask = \
            smooth_edges(arr <= value_thresh, filter_size, min_pixels)

    region_mask = \
        Ellipse2D(True, 0.0, 0.0, major * max_extent, minor * max_extent,
                  pa)(xx, yy).astype(bool)
    region_mask = nd.binary_dilation(region_mask, eight_conn, iterations=2)

    # The bubble center must fall within a valid region
    mid_pt = np.where(dist_arr == 0.0)
    if len(mid_pt[0]) == 0:
        middle_fail = True
    else:
        local_center = zip(*np.where(dist_arr == 0.0))[0]
        middle_fail = False
    # _make_bubble_mask(smooth_mask, local_center)

    # If the center is not contained within a bubble region, return
    # empties.
    bad_case = not smooth_mask.any() or smooth_mask.all() or \
        (smooth_mask * region_mask).all() or middle_fail
    if bad_case:
        if return_mask:
            return np.array([]), 0.0, 0.0, value_thresh, smooth_mask

        return np.array([]), 0.0, 0.0, value_thresh

    orig_perim = find_contours(region_mask, 0, fully_connected='high')[0]
    # new_perim = find_contours(smooth_mask, 0, fully_connected='high')
    coords = []
    extent_mask = np.zeros_like(region_mask)
    # for perim in new_perim:
    #     perim = perim.astype(np.int)
    #     good_pts = \
    #         np.array([pos for pos, pt in enumerate(perim)
    #                   if region_mask[pt[0], pt[1]]])
    #     if not good_pts.any():
    #         continue

    #     # Now split into sections
    #     from utils import consec_split
    #     split_pts = consec_split(good_pts)

    #     # Remove the duplicated end point if it was initially connected
    #     if len(split_pts) > 1:
    #         # Join these if the end pts initially matched
    #         if split_pts[0][0] == split_pts[-1][-1]:
    #             split_pts[0] = np.append(split_pts[0],
    #                                      split_pts[-1][::-1])
    #             split_pts.pop(-1)

    #     for split in split_pts:
    #         coords.append(perim[split])

    #     extent_mask[perim[good_pts][:, 0], perim[good_pts][:, 1]] = True

    # Based on the curvature of the shell, only fit points whose
    # orientation matches the assumed centre.
    # incoord, outcoord = shell_orientation(coords, local_center,
    #                                       verbose=False)

    # Now only keep the points that are not blocked from the centre pixel
    for pt in orig_perim:

        theta = np.arctan2(pt[0] - local_center[0], pt[1] - local_center[1])

        num_pts = int(
            np.round(np.hypot(pt[0] - local_center[0],
                              pt[1] - local_center[1]),
                     decimals=0))

        ys = np.round(np.linspace(local_center[0], pt[0], num_pts),
                      decimals=0).astype(np.int)

        xs = np.round(np.linspace(local_center[1], pt[1], num_pts),
                      decimals=0).astype(np.int)

        not_on_edge = np.logical_and(ys < smooth_mask.shape[0],
                                     xs < smooth_mask.shape[1])
        ys = ys[not_on_edge]
        xs = xs[not_on_edge]

        dist = np.sqrt((ys - local_center[0])**2 + (xs - local_center[1])**2)

        prof = smooth_mask[ys, xs]

        prof = prof[dist >= min_radius_frac * minor]
        ys = ys[dist >= min_radius_frac * minor]
        xs = xs[dist >= min_radius_frac * minor]

        # Look for the first 0 and ignore all others past it
        zeros = np.where(prof == 0)[0]

        # If none, move on
        if not zeros.any():
            continue

        edge = zeros[0]

        extent_mask[ys[edge], xs[edge]] = True
        coords.append((ys[edge], xs[edge]))
        shell_thetas.append(theta)

    # Calculate the fraction of the region associated with a shell
    shell_frac = len(shell_thetas) / float(len(orig_perim))

    shell_thetas = np.array(shell_thetas)
    coords = np.array(coords)

    # Use the theta values to find the standard deviation i.e. how
    # dispersed the shell locations are. Assumes a circle, but we only
    # consider moderately elongated ellipses, so the statistics approx.
    # hold.
    theta_var = np.sqrt(circvar(shell_thetas * u.rad)).value

    extent_coords = \
        np.vstack([pt + off for pt, off in
                   zip(np.where(extent_mask), offset)]).T

    if verbose:
        print("Shell fraction : " + str(shell_frac))
        print("Angular Std. : " + str(theta_var))
        import matplotlib.pyplot as p
        true_region_mask = \
            Ellipse2D(True, 0.0, 0.0, major, minor,
                      pa)(xx, yy).astype(bool)

        ax = p.subplot(121)
        ax.imshow(arr, origin='lower', interpolation='nearest')
        ax.contour(smooth_mask, colors='b')
        ax.contour(region_mask, colors='r')
        ax.contour(true_region_mask, colors='g')
        if len(coords) > 0:
            p.plot(coords[:, 1], coords[:, 0], 'bD')
        p.plot(local_center[1], local_center[0], 'gD')
        ax2 = p.subplot(122)
        ax2.imshow(extent_mask, origin='lower', interpolation='nearest')
        p.draw()
        raw_input("?")
        p.clf()

    if return_mask:
        return extent_coords, shell_frac, theta_var, value_thresh, \
            extent_mask

    return extent_coords, shell_frac, theta_var, value_thresh