Skip to content

Add annulus focal kernel #126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 3, 2020

Conversation

chase-dwelle
Copy link
Contributor

Addresses #125, #124

Using the circle kernel to extend to an annulus kernel. Implementation excludes the cells on the bound of the inner radius of the annulus.

Also implements the ability to return the raw z-scores from hotspots.

@chase-dwelle
Copy link
Contributor Author

Thinking the kernel should be "pure" and not include the focal point. Will push a change.

@thuydotm
Copy link
Contributor

thuydotm commented Sep 2, 2020

Thanks for the PR, I would love to have some tests with this annulus kernel. With the zscore option added to hotspots, I think we should have a separate function for it.

The ongoing stuff with focal is to allow some other kernel shapes (eg: cone, wedge) and also custom kernel. We'd better supply kernel value to a function instead of creating them inside the function, I believe. So basically, the interface should look be something like this:

def _validate_kernel_shape(custom_kernel, shape, radius, outer_radius, inner_radius, ...):
    if (shape == 'circle'  and radius is valid):
        if custom_kernelis not None or outer_radius is not None or inner_radius is not None:
             raise ValueError("""circular kernel must be specified by shape='circle' and a valid `radius`, recieved: ...""")
    # check other kernel shapes
    ....

def create_kernel(cellsize_x, cellsize_y, custom_kernel, shape, radius, outer_radius, inner_radius):
      _validate_kernel_shape()
      if shape == 'circle':
           kernel = _gen_circular_kernel(cellsize_x, cellsize_y, radius)
      elif shape == 'annulus':
           kernel = _gen_annulus_kernel(cellsize_x, cellsize_y, outer_radius, inner_radius)
      ....
      return kernel

def apply(raster, kernel, func):
      ....

@chase-dwelle
Copy link
Contributor Author

Thanks, will make these changes. Would it make sense to extend the kernel by passing **kwargs considering the expansion of kernel shapes? Could also pass it as a dictionary to make definition and declaration of kernels more explicit.

@thuydotm
Copy link
Contributor

thuydotm commented Sep 2, 2020

@chase-dwelle with the expansion of kernel shapes, I'm thinking that we can provide a bunch of functions that explicitly tell the shape in their names instead of having 1 function with a long list of args.

def circular_kernel(cellsize_x, cellsize_y, radius):
      # first validate args
      # create and return 2d array of kernel

def annulus_kernel(cellsize_x, cellsize_y, outer_radius, inner_radius):
      # first validate args
      # create and return 2d array of kernel 

def custom_kernel(kernel_values):
     ...

How do you think?

@thuydotm
Copy link
Contributor

thuydotm commented Sep 2, 2020

Anyway, these are some next steps. We're happy to have this PR merged once having tests updated.

@chase-dwelle
Copy link
Contributor Author

Added some tests for the kernels and made kernels a required argument to be passed to functions. The data flows go: raster -> cellsize -> kernel -> function/convolution, where cellsize and kernel are returned from functions and are used as arguments instead of passing kernel constructor information to each of the function/convolution methods.

This adds a couple more steps, but also is more straightforward from a code readability standpoint (in my opinion).

I think it might be reasonable to refactor kernel construction to a xrspatial/kernels.py in a future PR as kernel information is going to only grow more. Would that be reasonable @thuydotm ?

@thuydotm
Copy link
Contributor

thuydotm commented Sep 3, 2020

@chase-dwelle hey the PR looks good and we'll merge it now.

The data flow sounds good. Next step is to remove the function create_kernel. A kernel of any shape can be created directly by calling its corresponding function. It makes sense to assume that user knows which shape they want and which params related.

We should still have kernel functions in focal in my opinion since it's only used for focal stats currently.

@brendancol brendancol merged commit b13c9ed into makepath:master Sep 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants