Skip to content
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

Extension of transform module #124

Merged
merged 98 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 97 commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
503daca
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
c4d048a
Merge branch 'main' into transform
EnricoTrizio May 16, 2023
dcba920
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
4b351fd
Merge branch 'transform' of https://github.com/luigibonati/mlcolvar i…
EnricoTrizio May 18, 2023
d0703df
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
74bfefc
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
4ac1846
Merge branch 'transform' of https://github.com/luigibonati/mlcolvar i…
EnricoTrizio Jun 1, 2023
3ee0c03
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
d76ee74
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
70bb151
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
2ec5867
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
d64ec8f
Merge branch 'transform' of https://github.com/luigibonati/mlcolvar i…
EnricoTrizio Jun 7, 2023
03d7d8f
Added return bins to KDE
EnricoTrizio Jun 7, 2023
0e65b5a
Added RDF transform
EnricoTrizio Jun 7, 2023
62d86bd
Fixed output shape of rdf transform
EnricoTrizio Jun 8, 2023
4387073
Fix device in distances
EnricoTrizio Oct 23, 2023
7b01a46
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
c3bdc14
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
756b93d
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
056fac9
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
fa9beb9
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
92451ca
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
33d5e35
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
476de1b
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
a3796e3
Added return bins to KDE
EnricoTrizio Jun 7, 2023
c4797ac
Added RDF transform
EnricoTrizio Jun 7, 2023
7436fc4
Fixed output shape of rdf transform
EnricoTrizio Jun 8, 2023
e130ad6
Fix device in distances
EnricoTrizio Oct 23, 2023
f02b4e8
Merge branch 'transform' of https://github.com/luigibonati/mlcolvar i…
EnricoTrizio Nov 8, 2023
65db607
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
bbf7b08
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
3bdb9a9
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
0d7991b
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
ab72dc2
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
cc9c006
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
51f69ca
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
51e73d5
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
4ccf021
Added return bins to KDE
EnricoTrizio Jun 7, 2023
b2cc310
Added RDF transform
EnricoTrizio Jun 7, 2023
5866356
Fixed output shape of rdf transform
EnricoTrizio Jun 8, 2023
b018d07
Fix device in distances
EnricoTrizio Oct 23, 2023
cb097e8
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
6fb6dab
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
2ce5b77
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
ad6ded5
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
e9dc215
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
70085fe
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
4cb727e
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
56e1b6e
Rebuilt transform branch due to conflicts on deleted files with main
EnricoTrizio May 16, 2023
824de72
Added return bins to KDE
EnricoTrizio Jun 7, 2023
b5e9493
Added RDF transform
EnricoTrizio Jun 7, 2023
bf52dd8
Fixed output shape of rdf transform
EnricoTrizio Jun 8, 2023
e0a7ed5
Fix device in distances
EnricoTrizio Oct 23, 2023
a6f9b0f
Merge branch 'transform' of https://github.com/luigibonati/mlcolvar i…
EnricoTrizio Nov 14, 2023
67321f0
Added torsional angle transform
EnricoTrizio Mar 12, 2024
8780a49
Added shape_sanitizer functions for cell and positions
EnricoTrizio Mar 12, 2024
3707076
Fixed part of transform utils tests
EnricoTrizio Mar 12, 2024
aab85b3
Fixed docstring
EnricoTrizio Mar 20, 2024
cf141e0
Added slicing of output distances
EnricoTrizio Mar 20, 2024
4411cc8
removed print from test function
EnricoTrizio Mar 20, 2024
d701ce5
Fixed position sanitize
EnricoTrizio Apr 4, 2024
1fc1e8c
Create coordination number traasform
EnricoTrizio Apr 4, 2024
a3724f5
fixed getattr to select swtich name
EnricoTrizio Apr 4, 2024
52d8061
fixed typos
EnricoTrizio Apr 4, 2024
d7d8c8b
Improved test
EnricoTrizio Apr 4, 2024
551ad2e
Redefined inverse method of Inverse wrapper class
EnricoTrizio Apr 4, 2024
87b5e3a
Removed pytest import if not needed
EnricoTrizio Apr 8, 2024
4b2e0dc
removed unused variables
EnricoTrizio Apr 8, 2024
42f3f6a
Added check on cutoff application mode
EnricoTrizio Apr 8, 2024
4abb0e2
Fixed keyword error in forward
EnricoTrizio Apr 8, 2024
ac01439
Divided transform into tools and descriptors
EnricoTrizio Apr 10, 2024
fb16117
Removed statistics from descriptors utils
EnricoTrizio Apr 10, 2024
0a0063e
Made absolute coordinates the default for distance-based transforms, …
EnricoTrizio May 2, 2024
001bb0f
Polishing and improving docs and tests
EnricoTrizio May 2, 2024
9be6176
Fixed imports for tools/descriptors structure and removed useless cla…
EnricoTrizio May 3, 2024
595f8b2
Changed ContHIst to ContinuousHistogram
EnricoTrizio May 3, 2024
e675f32
fixed typing
EnricoTrizio May 3, 2024
bb449b4
removed leftover test file
EnricoTrizio May 3, 2024
ec851af
Temporarily removed MacOS from testing
EnricoTrizio May 3, 2024
50c9953
Explicitly added _accumulate as dismissed from PyTorch
EnricoTrizio May 3, 2024
57e468d
Merge branch 'main' into transform
EnricoTrizio May 3, 2024
78e9c90
removed non used variables
EnricoTrizio May 3, 2024
baefb6c
added tests to test suite
EnricoTrizio May 3, 2024
7b60ccd
Moved Statistics back to transform.utils
EnricoTrizio May 7, 2024
e52c3ee
Merge branch 'main' into transform
EnricoTrizio May 7, 2024
d3741bb
Fixed import and test after moving Statistics to transform.utils
EnricoTrizio May 7, 2024
49e0ed7
Merge branch 'transform' of https://github.com/luigibonati/mlcolvar i…
EnricoTrizio May 7, 2024
2ea7159
Merge distance functions into a single one with vector distance key
EnricoTrizio May 7, 2024
204bed0
Moved variables to private and fixed reordering bug
EnricoTrizio May 7, 2024
9fb5c4e
removed typos and change input of forward from x to pos as for other …
EnricoTrizio May 7, 2024
c8ed9ac
Changed slicing to atom pairs list
EnricoTrizio May 7, 2024
78ada65
removed code ashes
EnricoTrizio May 7, 2024
25b0ff8
Fixed out_features with slicing option
EnricoTrizio May 8, 2024
c443fc2
Added multiple descriptors wrapper class
EnricoTrizio May 8, 2024
aee5c97
Improved formatting of classes and functions
EnricoTrizio May 8, 2024
f23ab1e
Fixed typo in test function
EnricoTrizio May 8, 2024
9d827fa
add doc entries for descriptors
luigibonati May 8, 2024
c81eb2f
Improved docs for transform
EnricoTrizio May 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/api_core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,17 @@ These are the building blocks which are used to construct the CVs.

Transform
Normalization


.. currentmodule:: mlcolvar.core.transform.descriptors

.. autosummary::
:toctree: autosummary
:template: custom-class-template.rst

PairwiseDistances
TorsionalAngle
CoordinationNumbers
EigsAdjMat
MultipleDescriptors

2 changes: 1 addition & 1 deletion mlcolvar/core/stats/tica.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
compute_average,
reduced_rank_eig,
)
from mlcolvar.core.transform.utils import batch_reshape
from mlcolvar.core.transform.tools.utils import batch_reshape
import warnings


Expand Down
5 changes: 3 additions & 2 deletions mlcolvar/core/transform/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
__all__ = ["Transform", "Normalization", "Statistics", "Inverse"]
__all__ = ["Transform","Normalization","Statistics","SwitchingFunctions","MultipleDescriptors","PairwiseDistances","EigsAdjMat","ContinuousHistogram","Inverse",'TorsionalAngle']

from .transform import *
from .normalization import *
from .utils import *
from .tools import *
from .descriptors import *
7 changes: 7 additions & 0 deletions mlcolvar/core/transform/descriptors/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
__all__ = ["MultipleDescriptors", "CoordinationNumbers", "EigsAdjMat", "PairwiseDistances", "TorsionalAngle"]

from .coordination_numbers import *
from .eigs_adjacency_matrix import *
from .pairwise_distances import *
from .torsional_angle import *
from .multiple_descriptors import *
202 changes: 202 additions & 0 deletions mlcolvar/core/transform/descriptors/coordination_numbers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import torch
import numpy as np

from mlcolvar.core.transform import Transform
from mlcolvar.core.transform.descriptors.utils import compute_distances_matrix, apply_cutoff, sanitize_positions_shape

from typing import Union

__all__ = ["CoordinationNumbers"]

class CoordinationNumbers(Transform):
"""
Coordination number transform, compute the coordination number between the elements of two groups of atoms for a set of atoms from their positions
"""

def __init__(self,
group_A: list,
group_B: list,
cutoff: float,
n_atoms: int,
PBC: bool,
cell: Union[float, list],
mode: str,
scaled_coords: bool = False,
switching_function = None) -> torch.Tensor:
"""Initialize a coordination number object between two groups of atoms A and B.

Parameters
----------
group_A : list
Zero-based indices of group A atoms
group_B : list
Zero-based indices of group B atoms
cutoff : float
Cutoff radius for coordination number evaluation
n_atoms : int
Total number of atoms in the system
PBC : bool
Switch for Periodic Boundary Conditions use
cell : Union[float, list]
Dimensions of the real cell, orthorombic-like cells only
mode : str
Mode for cutoff application, either:
- 'continuous': applies a switching function to the distances which can be specified with switching_function keyword, has stable derivatives
- 'discontinuous': set at zero everything above the cutoff and one below, derivatives may be be incorrect
scaled_coords : bool
Switch for coordinates scaled on cell's vectors use, by default False
switching_function : _type_, optional
Switching function to be applied for the cutoff, can be either initialized as a switching_functions/SwitchingFunctions class or a simple function, by default None

Returns
-------
torch.Tensor
Coordination numbers of elements of group A with respect to elements of group B
"""
super().__init__(in_features=int(n_atoms*3), out_features=len(group_A))

# parse args
self.group_A = group_A
self._group_A_size = len(group_A)
self.group_B = group_B
self._group_B_size = len(group_B)
self._reordering = np.concatenate((self.group_A, self.group_B))
self.cutoff = cutoff
self.n_atoms = n_atoms
self.PBC = PBC
self.cell = cell
self.scaled_coords = scaled_coords
self.mode = mode
self.switching_function = switching_function

def compute_coordination_number(self, pos):
# move the group A elements to first positions
pos, batch_size = sanitize_positions_shape(pos, self.n_atoms)
pos = pos[:, self._reordering, :]
dist = compute_distances_matrix(pos=pos,
n_atoms=self.n_atoms,
PBC=self.PBC,
cell=self.cell,
scaled_coords=self.scaled_coords)

# we can apply the switching cutoff with the switching function
contributions = apply_cutoff(x=dist,
cutoff=self.cutoff,
mode=self.mode,
switching_function=self.switching_function)

# we can throw away part of the matrix as it is repeated uselessly
contributions = contributions[:, :self._group_A_size, :]

# and also ensure that the AxA part of the matrix is zero, we need also to preserve the gradients
mask = torch.ones_like(contributions)
mask[:, :self._group_A_size, :self._group_A_size] = 0
contributions = contributions*mask

# compute coordination
coord_numbers = torch.sum(contributions, dim=-1)

return coord_numbers

def forward(self, pos):
coord_numbers = self.compute_coordination_number(pos)
return coord_numbers


def test_coordination_number():
from mlcolvar.core.transform.tools.switching_functions import SwitchingFunctions

# simple example based on calixarene water coordination numbers
pos = torch.Tensor([[[-0.410219, -0.680065, -2.016121],
[-0.164329, -0.630426, -2.120843],
[-0.250341, -0.392700, -1.534535],
[-0.277187, -0.615506, -1.335904],
[-0.762276, -1.041939, -1.546581],
[-0.200766, -0.851481, -1.534129],
[ 0.051099, -0.898884, -1.628219],
[-1.257225, 1.671602, 0.166190],
[-0.486917, -0.902610, -1.554715],
[-0.020386, -0.566621, -1.597171],
[-0.507683, -0.541252, -1.540805],
[-0.527323, -0.206236, -1.532587]],
[[-0.410387, -0.677657, -2.018355],
[-0.163502, -0.626094, -2.123348],
[-0.250672, -0.389610, -1.536810],
[-0.275395, -0.612535, -1.338175],
[-0.762197, -1.037856, -1.547382],
[-0.200948, -0.847825, -1.536010],
[ 0.051170, -0.896311, -1.629396],
[-1.257530, 1.674078, 0.165089],
[-0.486894, -0.900076, -1.556366],
[-0.020235, -0.563252, -1.601229],
[-0.507242, -0.537527, -1.543025],
[-0.528576, -0.202031, -1.534733]]])

cell = 4.0273098
pos.requires_grad = True

n_atoms = 12
cutoff=0.25
switching_function=SwitchingFunctions(in_features=n_atoms*3, name='Rational', cutoff=cutoff, options={'n': 2, 'm' : 6, 'eps' : 1e0})

model = CoordinationNumbers(group_A=[0, 1],
group_B=[2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
cutoff=cutoff,
n_atoms=n_atoms,
PBC=True,
cell=cell,
mode='continuous',
scaled_coords=False,
switching_function=switching_function)

out = model(pos)
out.sum().backward()

# we swap by hand the 0,1 atoms with 2,3
pos = torch.Tensor([[[-0.250341, -0.392700, -1.534535],
[-0.277187, -0.615506, -1.335904],
[-0.410219, -0.680065, -2.016121],
[-0.164329, -0.630426, -2.120843],
[-0.762276, -1.041939, -1.546581],
[-0.200766, -0.851481, -1.534129],
[ 0.051099, -0.898884, -1.628219],
[-1.257225, 1.671602, 0.166190],
[-0.486917, -0.902610, -1.554715],
[-0.020386, -0.566621, -1.597171],
[-0.507683, -0.541252, -1.540805],
[-0.527323, -0.206236, -1.532587]],
[[-0.250672, -0.389610, -1.536810],
[-0.275395, -0.612535, -1.338175],
[-0.410387, -0.677657, -2.018355],
[-0.163502, -0.626094, -2.123348],
[-0.762197, -1.037856, -1.547382],
[-0.200948, -0.847825, -1.536010],
[ 0.051170, -0.896311, -1.629396],
[-1.257530, 1.674078, 0.165089],
[-0.486894, -0.900076, -1.556366],
[-0.020235, -0.563252, -1.601229],
[-0.507242, -0.537527, -1.543025],
[-0.528576, -0.202031, -1.534733]]])

pos.requires_grad = True
switching_function=SwitchingFunctions(in_features=n_atoms*3, name='Rational', cutoff=cutoff, options={'n': 2, 'm' : 6, 'eps' : 1e0})

model = CoordinationNumbers(group_A=[2, 3],
group_B=[0, 1, 4, 5, 6, 7, 8, 9, 10, 11],
cutoff=cutoff,
n_atoms=n_atoms,
PBC=True,
cell=cell,
mode='continuous',
scaled_coords=False,
switching_function=switching_function)

out_2 = model(pos)
out_2.sum().backward()
assert(torch.allclose(out, out_2))

# TODO add reference value for check

if __name__ == "__main__":
test_coordination_number()

118 changes: 118 additions & 0 deletions mlcolvar/core/transform/descriptors/eigs_adjacency_matrix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import torch

from mlcolvar.core.transform import Transform
from mlcolvar.core.transform.descriptors.utils import compute_adjacency_matrix

from typing import Union

__all__ = ["EigsAdjMat"]

class EigsAdjMat(Transform):
"""
Eigenvalues of adjacency matrix transform, compute the eigenvalues of the adjacency matrix for a set of atoms from their positions
"""

def __init__(self,
mode: str,
cutoff: float,
n_atoms: int,
PBC: bool,
cell: Union[float, list],
scaled_coords: bool = False,
switching_function = None) -> torch.Tensor:
"""Initialize an eigenvalues of an adjacency matrix object.

Parameters
----------
mode : str
Mode for cutoff application, either:
- 'continuous': applies a switching function to the distances which can be specified with switching_function keyword, has stable derivatives
- 'discontinuous': set at zero everything above the cutoff and one below, derivatives may be be incorrect
cutoff : float
Cutoff for the adjacency criterion
n_atoms : int
Number of atoms in the system
PBC : bool
Switch for Periodic Boundary Conditions use
cell : Union[float, list]
Dimensions of the real cell, orthorombic-like cells only
scaled_coords : bool
Switch for coordinates scaled on cell's vectors use, by default False
switching_function : _type_, optional
Switching function to be applied for the cutoff, can be either initialized as a switching_functions/SwitchingFunctions class or a simple function, by default None

Returns
-------
torch.Tensor
Adjacency matrix of all the n_atoms according to cutoff
"""
super().__init__(in_features=int(n_atoms*3), out_features=n_atoms)

# parse args
self.mode = mode
self.cutoff = cutoff
self.n_atoms = n_atoms
self.PBC = PBC
self.cell = cell
self.scaled_coords = scaled_coords
self.switching_function = switching_function

def compute_adjacency_matrix(self, pos):
pos = compute_adjacency_matrix(pos=pos,
mode=self.mode,
cutoff=self.cutoff,
n_atoms=self.n_atoms,
PBC=self.PBC,
cell=self.cell,
scaled_coords=self.scaled_coords,
switching_function=self.switching_function)
return pos

def get_eigenvalues(self, x):
eigs = torch.linalg.eigvalsh(x)
return eigs

def forward(self, x: torch.Tensor):
x = self.compute_adjacency_matrix(x)
eigs = self.get_eigenvalues(x)
return eigs

def test_eigs_of_adj_matrix():
from mlcolvar.core.transform.tools.switching_functions import SwitchingFunctions

n_atoms=2
pos = torch.Tensor([ [ [0., 0., 0.],
[1., 1., 1.] ],
[ [0., 0., 0.],
[1., 1.1, 1.] ] ]
)
pos.requires_grad = True
cell = torch.Tensor([1., 2., 1.])

cutoff = 1.8
switching_function=SwitchingFunctions(in_features=n_atoms*3, name='Fermi', cutoff=cutoff, options={'q':0.05})

model = EigsAdjMat(mode='continuous',
cutoff=cutoff,
n_atoms=n_atoms,
PBC=True,
cell=cell,
scaled_coords=False,
switching_function=switching_function)
out = model(pos)
Fixed Show fixed Hide fixed
out.sum().backward()

pos = torch.einsum('bij,j->bij', pos, 1/cell)
model = EigsAdjMat(mode='continuous',
cutoff=cutoff,
n_atoms=n_atoms,
PBC=True,
cell=cell,
scaled_coords=True,
switching_function=switching_function)
out = model(pos)
assert(out.shape[-1] == model.out_features)
out.sum().backward()

if __name__ == "__main__":
test_eigs_of_adj_matrix()
Loading
Loading