freud
freud copied to clipboard
Weighted local density
I'm interested in using the local density submodule, but we would like to have the option to weight the calculation. I saw that you have a sort of linear weighting after a cutoff, but it would be nice to be able to use a custom weighting function based on the distance, r.
@scmartin What weighting function do you have in mind? The function is used in the C++ internals, so you'd need a way to express that Python function in C++. If it's just one specific function you're thinking of, perhaps that could be an option to the class constructor, like weighting='linear'
or weighting='quadratic'
.
Here's the implementation: https://github.com/glotzerlab/freud/blob/2ae4a793b049f9c853c409ecdb55a060238e4467/cpp/density/LocalDensity.cc#L37-L50
Another way to implement this would be to use a custom NeighborList
object with the weights
set to your desired values, and have an option for weighted=True
that reads from the NeighborList
weights. This would mirror the behavior of Steinhardt
's weighted option. This might be cleaner because it would let users pick whatever weights they want. See the Steinhardt docs and this notebook for a code example.
@bdice I was considering a gaussian weighting function. It would be nice to have a general weighting function, but I haven't looked at the C++ codebase yet, and haven't considered how to pass a python function to the C++ code.
@bdice's suggestion to use the NeighborList weights is probably the most straightforward option right now. You can construct the exact set of neighbors that LocalDensity would by using the same query arguments, then assign the weights according to your function (e.g. a Gaussian). That would require a relatively simple change to the LocalDensity class in its current form.
It's certainly possible to enable a Python callback. It's not something we've done anywhere in freud, but Cython does have that functionality. Here's the example from the Cython docs. However, to avoid slowing down the default code path we would have to make sure that a callback to Python is only performed when the user requests it, the default code path should still be a constant. Also, since this would be a more complex solution, I would probably want to make sure that it's not functionality that we could enable using the current (weighted) NeighborList API, or at least that there's a compelling reason to choose the callback approach.
@vyasr the neighbor list option seems like a reasonable approach that would make assigning the weights in python simple and flexible as a user, and then passing the weights to the local density function similar to the steinhardt ordered parameter.
@scmartin would you be interested in trying to enable that? It should be pretty straightforward I think. If you look at the code snippet Bradley posted above, you would simply replace adding 1.0 with adding nb.weight (also in the else clause there). Then you would need to modify the APIs to indicate that you are providing a weighted NeighborList.
I'll give it a shot
@scmartin have you had any luck with this? Let us know if you need some pointers.
Sorry, I haven't had a chance to implement it yet. I'm trying a different method for my analysis, so I'm this has taken a backseat while I try this new method.
No worries, I just wanted to make sure that you weren't stuck spinning your wheels.