Skip to content

Change categories for general purpose #369

@zerothi

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions