-
Notifications
You must be signed in to change notification settings - Fork 3
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
Orientational sites #307
Orientational sites #307
Changes from 5 commits
2ab7f6a
167e975
387e661
309fe8a
6248ee0
1b12bd7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -14,6 +14,7 @@ | |||||||||||
from scipy.constants import physical_constants | ||||||||||||
from skimage.feature import blob_dog | ||||||||||||
from skimage.measure import regionprops | ||||||||||||
from gemdat.utils import calculate_spherical_areas | ||||||||||||
|
||||||||||||
from .segmentation import watershed_pbc | ||||||||||||
|
||||||||||||
|
@@ -24,6 +25,7 @@ | |||||||||||
|
||||||||||||
from gemdat.path import Pathway | ||||||||||||
from gemdat.trajectory import Trajectory | ||||||||||||
from gemdat.orientations import Orientations | ||||||||||||
|
||||||||||||
|
||||||||||||
@dataclass | ||||||||||||
|
@@ -442,6 +444,51 @@ def optimal_percolating_path(self, **kwargs) -> Pathway | None: | |||||||||||
return optimal_percolating_path(self, **kwargs) | ||||||||||||
|
||||||||||||
|
||||||||||||
class OrientationalVolume(Volume): | ||||||||||||
"""Container for orientational volume data, that are in spherical | ||||||||||||
coordinates.""" | ||||||||||||
shape: tuple[int, int] | ||||||||||||
radii: np.ndarray | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not convinced that subclassing Volume makes sense here. The other methods on Volume will not work with the data being passed for the OrientationalVolume.
Comment on lines
+457
to
+458
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Radii and shape are not used, I'd recommend removing them from this class.
Suggested change
|
||||||||||||
|
||||||||||||
def __init__(self, shape, radii, *args, **kwargs): | ||||||||||||
super().__init__(*args, **kwargs) | ||||||||||||
self.shape = shape | ||||||||||||
self.radii = radii | ||||||||||||
|
||||||||||||
def orientational_peaks( | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have
Suggested change
|
||||||||||||
self, | ||||||||||||
**kwargs, | ||||||||||||
) -> list: | ||||||||||||
"""Find peaks using the [Difference of | ||||||||||||
Gaussian][skimage.feature.blob_dog] function in [scikit- | ||||||||||||
image][skimage]. | ||||||||||||
|
||||||||||||
Parameters | ||||||||||||
---------- | ||||||||||||
**kwargs | ||||||||||||
Additional keyword arguments are passed to [skimage.feature.blob_dog][] | ||||||||||||
|
||||||||||||
Returns | ||||||||||||
------- | ||||||||||||
peaks : list | ||||||||||||
List of coordinates of the peaks | ||||||||||||
""" | ||||||||||||
kwargs.setdefault('threshold', 0.1) | ||||||||||||
|
||||||||||||
theta, phi, values = self.data.T | ||||||||||||
|
||||||||||||
x = theta | ||||||||||||
y = phi | ||||||||||||
Comment on lines
+485
to
+488
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
z = values / values.max() | ||||||||||||
|
||||||||||||
blobs = blob_dog(z, **kwargs) | ||||||||||||
|
||||||||||||
peaks = [(y[int(i), int(j)], x[int(i), int(j)]) | ||||||||||||
for i, j, sigma in blobs] | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
|
||||||||||||
return peaks | ||||||||||||
|
||||||||||||
|
||||||||||||
def trajectory_to_volume( | ||||||||||||
trajectory: Trajectory, | ||||||||||||
resolution: float = 0.2, | ||||||||||||
|
@@ -502,3 +549,60 @@ def trajectory_to_volume( | |||||||||||
label='trajectory', | ||||||||||||
units=None, | ||||||||||||
) | ||||||||||||
|
||||||||||||
|
||||||||||||
def orientations_to_volume( | ||||||||||||
orientations: Orientations, | ||||||||||||
shape: tuple[int, int], | ||||||||||||
normalize_area: bool, | ||||||||||||
) -> OrientationalVolume: | ||||||||||||
"""Calculate density volume from orientation. | ||||||||||||
|
||||||||||||
The orientations are converted in spherical coordinates, | ||||||||||||
and the azimutal and elevation angles are binned into a 2d histogram. | ||||||||||||
|
||||||||||||
Parameters | ||||||||||||
---------- | ||||||||||||
orientations : Orientations | ||||||||||||
Input orientations | ||||||||||||
shape : tuple | ||||||||||||
The shape of the spherical sector in which the trajectory is | ||||||||||||
normalize_area : bool | ||||||||||||
If True, normalize the histogram by the area of the bins | ||||||||||||
|
||||||||||||
Returns | ||||||||||||
------- | ||||||||||||
vol : OrientationalVolume | ||||||||||||
Output volume | ||||||||||||
""" | ||||||||||||
az, el, r = orientations.vectors_spherical.T | ||||||||||||
az = az.flatten() | ||||||||||||
el = el.flatten() | ||||||||||||
|
||||||||||||
hist, _, _ = np.histogram2d(el, az, shape) | ||||||||||||
|
||||||||||||
if normalize_area: | ||||||||||||
# Normalize by the area of the bins | ||||||||||||
areas = calculate_spherical_areas(shape) | ||||||||||||
hist = np.divide(hist, areas) | ||||||||||||
# Drop the bins at the poles where normalization is not possible | ||||||||||||
hist = hist[1:-1, :] | ||||||||||||
|
||||||||||||
values = hist.T | ||||||||||||
axis_phi, axis_theta = values.shape | ||||||||||||
|
||||||||||||
phi = np.linspace(0, 360, axis_phi) | ||||||||||||
theta = np.linspace(0, 180, axis_theta) | ||||||||||||
|
||||||||||||
theta, phi = np.meshgrid(theta, phi) | ||||||||||||
|
||||||||||||
data = np.stack([theta, phi, values], axis=-1) | ||||||||||||
|
||||||||||||
return OrientationalVolume( | ||||||||||||
data=data, | ||||||||||||
shape=shape, | ||||||||||||
radii=r, | ||||||||||||
lattice=orientations.trajectory.get_lattice(), | ||||||||||||
label='orientations', | ||||||||||||
units=None, | ||||||||||||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this something like:
The histogram can be re-used to get the peaks.