Skip to content

Change categories for general purpose #369

Description

@zerothi

Describe the feature

Currently the Categories used for geometries are limited in use. @tfrederiksen initial idea in #202 spawned this whole category stuff. Now the problem with the categories is that they are only based on 1 atoms at a time. Which doesn't really make it useful for other categories.

Currently a category dose more or less these things:

  1. Create the categories via boolean operators making composite categories.
  2. When trying to categorise a geometry every atom is looped individually meaning that every atom gets assigned a single category (possibly a NullCategory).
    import sisl as si
    gr = si.geom.graphene()
    print(si.geom.AtomOdd().categorize(gr))
    returns [ø, odd].
  3. The categorize function will only ever return a single category for each atom. This means that one cannot create categories that encompass multiple atoms, say dihedral angle requirements etc.

What I suggest is that we change the categories to return a CategoryResult which contains 1) the category it resulted in and 2) any arguments that fits the category. I.e. a CategoryNeighbour may contain the atom index, and that atoms neighbours. This means that it has some state knowledge which I kind of objected against previously. However, since now the results are deferred to another object I think it becomes more stable.
This however makes it a bit more problematic to use since one needs to easily decide which atoms belongs to which categories, and vice versa.

I am thinking about an interface that looks something like this:

# using addition we request that both be evaluated
odd = AtomOdd()
even = AtomEven()
cat = odd + even
# using boolean operators silently disregards those that are not part of them
# in this case they will return the same as above since they are from two distinct sets
cat = odd | even
results = cat.categorize(geometry)
# get the list of atoms that matches the category odd
# I am thinking that result(odd) should do the same?
# Is there anything a result should be doing
atoms = results.get(odd)
# get the categories that atom 1 matches (there may be more)
cats = results.get(1)
# one should be able to loop the different results over the different categories
for result, atoms in results:
    # the result is a class of CategoryResult as defined above
    result.category
    # each result may have specific attributes associated such that one can see
    # specific details for the category, say the neighbour indices etc.

Note that since a category result may have additional data associated we could expect it to retain information related to the category it self.

neighbours = AtomNeighbours(n=3) # or something
results = neighbours.categorize(geometry)
for result, atoms in results:
    cat = result.category

It isn't totally clear to me exactly what the interface should look like here, perhaps the easiest is if the result category for neighbours only has a single atom associated, and the result.neighbours is the list of neighbour indices?

ideas; suggestions etc. are most welcome @pfebrer and @tfrederiksen.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions