Skip to content

Add Structure.sublattices and class RandomStructureTransformation to standard_transformations.py #3057

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

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2398a05
Adding property to pymatgen/core/structure.py; additing class to py…
exenGT Jun 9, 2023
72924bf
pre-commit auto-fixes
pre-commit-ci[bot] Jun 10, 2023
f77b6c0
Add package dependencies in pymatgen/transformations/standard_transfo…
exenGT Jun 10, 2023
450c47d
pre-commit auto-fixes
pre-commit-ci[bot] Jun 10, 2023
7a4815b
Change print to raise for exception in method random_assign
exenGT Jun 10, 2023
7d9cab8
Fix linting errors
exenGT Jun 10, 2023
eb793ae
pre-commit auto-fixes
pre-commit-ci[bot] Jun 10, 2023
dfc74e4
Changes lengths variable type
exenGT Jun 10, 2023
20928c7
pre-commit auto-fixes
pre-commit-ci[bot] Jun 10, 2023
5449ed0
remove return type of function random_assign()
exenGT Jun 11, 2023
84f7832
Changed codes according to Janosh's suggestions.
exenGT Jun 16, 2023
353da7f
Update coord_cython.pyx
exenGT Aug 16, 2023
47869a7
Merge remote-tracking branch 'upstream/master' into dev
exenGT Aug 16, 2023
4e8fea7
Merge remote-tracking branch 'upstream/master' into dev
exenGT Aug 19, 2023
e0f40f7
Adding a test for class RandomStructureTransformation; change int to …
exenGT Aug 19, 2023
3a2ebc7
Adding docstring for __init__() of class RandomStructureTransformation.
exenGT Aug 19, 2023
b72f962
pre-commit auto-fixes
pre-commit-ci[bot] Aug 19, 2023
24d9689
Merge branch 'master' into dev
exenGT Oct 17, 2023
3285df6
Adding functionality to read ASE trajectory file in method from_file(…
exenGT Oct 20, 2023
5f0550a
Merge branch 'master' of https://github.com/materialsproject/pymatgen…
exenGT Oct 21, 2023
81dd21b
pre-commit auto-fixes
pre-commit-ci[bot] Oct 21, 2023
a8defc1
Change elif to if in from_file() in class Trajectory.
exenGT Oct 21, 2023
9b84cc2
Change elif to if in from_file() in class Trajectory.
exenGT Oct 21, 2023
766f062
pre-commit auto-fixes
pre-commit-ci[bot] Oct 21, 2023
5d6f238
revert changes from other PR mixed in
janosh Dec 23, 2023
e32fd8f
make all_structures not class attr
janosh Dec 23, 2023
4591156
cleanup random_assign
janosh Dec 23, 2023
5f1de0b
Added test_random_assign() in tests/transformations/test_standard_tra…
exenGT Dec 23, 2023
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
15 changes: 15 additions & 0 deletions pymatgen/core/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,21 @@ def is_ordered(self) -> bool:
"""
return all(site.is_ordered for site in self)

@property
def sublattices(self) -> dict[Composition, list]:
"""
Returns a list of lists of atom indices belonging to every unique
sublattice.
"""
unique_species_and_occu = set(self.species_and_occu)

sublattices_dict = dict()

for usp in unique_species_and_occu:
sublattices_dict[usp] = [i for i, sp in enumerate(self.species_and_occu) if sp == usp]

return sublattices_dict

def get_angle(self, i: int, j: int, k: int) -> float:
"""
Returns angle specified by three sites.
Expand Down
79 changes: 79 additions & 0 deletions pymatgen/transformations/standard_transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from __future__ import annotations

import logging
import random
from fractions import Fraction
from typing import TYPE_CHECKING

Expand Down Expand Up @@ -494,6 +495,84 @@ def inverse(self):
return


class RandomStructureTransformation(AbstractTransformation):
"""
Transform a disordered structure into a given number of random ordered structures.
"""

def __init__(self):
pass

def apply_transformation(self, structure: Structure, num_copies: int):
"""
For this transformation, the apply_transformation method will return
a random ordered structure from the given disordered structure.
"""
subl = structure.sublattices

# fill the sublattice sites with pure-element atoms
self.all_structures = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it necessary to store the structures on the transformation instance? might balloon mem usage if people create many of these RandomStructureTransformations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used this syntax because there is an is_one_to_many property in the class; should it be False by default? (I see it is True for other classes)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's no connection between is_one_to_many (that part is good) and storing the transformed structures on the transformation instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate more on this? I feel I'm not totally understanding. For example, the apply_transformation method of OrderDisorderedTransformation returns a list of structures as well (self._all_structures). What is the issue with this approach?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain the need to store all structures for later? Why not just return them and let them be garbage collected if they go out of scope in the user's code? Currently they live as long as the Transformation instance which is not great given structures are notoriously mem hungry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. This feature is here simply because I'm copying what's been written for the other transformations. If you think it's not a good approach, then I can modify it in my code accordingly.


for _ in range(num_copies):
new_structure = structure.copy()

for subl_comp, subl_indices in subl.items():
# convert composition into a dictionary
subl_comp_dict = subl_comp.as_dict()

el_list = list(subl_comp_dict.keys())
el_concs = list(subl_comp_dict.values())
lengths = [int(el_conc * len(subl_indices)) for el_conc in el_concs]

# randomly choose site indices for each element present in the sublattice

el_indices = self.random_assign(sequence=subl_indices, lengths=lengths)

for i_el, el in enumerate(el_list):
new_structure[el_indices[i_el]] = el

self.all_structures.append(new_structure)

return self.all_structures

@property
def inverse(self):
"""
Returns: None
"""
return

@property
def is_one_to_many(self) -> bool:
"""
Returns: True
"""
return True

def random_assign(self, sequence: list[int], lengths: list[int]):
"""
Randomly assign sublists in sequence with given lengths
"""
random.shuffle(sequence)

assignments = []

start_pos = 0

for length in lengths:
end_pos = min(start_pos + length, len(sequence))

## check if end_pos is greater than start_pos
if end_pos > start_pos:
assignments.append(sequence[start_pos:end_pos])
start_pos = end_pos

else:
raise Exception("Sum of lengths must be equal to the length of the sequence!")

return assignments


class OrderDisorderedStructureTransformation(AbstractTransformation):
"""
Order a disordered structure. The disordered structure must be oxidation
Expand Down
2 changes: 1 addition & 1 deletion requirements-optional.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ f90nml>=1.4.3
seekpath>=2.0.1
jarvis-tools>=2022.9.16
galore>=0.7.0
matgl>=0.5.1
matgl>=0.5.1