Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
656e9e1
Add _str2num and _deg2rad _utils
janbridley Apr 5, 2024
1e74eb7
Add cif file keys list to sample data
janbridley Apr 5, 2024
c369fd1
Add key_value_pairs reader and cell_params reader to parse
janbridley Apr 5, 2024
672c4e3
Add tests for key reader
janbridley Apr 5, 2024
e0b693f
Add tests for new utils
janbridley Apr 5, 2024
79350fc
Reorder test_key_reader
janbridley Apr 5, 2024
04b3344
Improve documentation for regex
janbridley Apr 5, 2024
b59eab1
Add warnings and tests to read_key_value_pairs
janbridley Apr 5, 2024
87303b9
Restore trailing spaces to downloaded CIF files
janbridley Apr 8, 2024
90120c7
Properly track keys containing "-"
janbridley Apr 8, 2024
d4203da
Improved tests for key value pair reader
janbridley Apr 8, 2024
8c3c014
Add key-value tests for INTENTIONALLY_BAD_CIF.cif
janbridley Apr 8, 2024
9c91bde
Fix docs
janbridley Apr 8, 2024
9aaba90
Enable top of page button
janbridley Apr 8, 2024
6ea7882
Update brand primary colors
janbridley Apr 8, 2024
0169783
Improve docs for parse.py
janbridley Apr 8, 2024
a404d19
Add __future__.annotations imports to relevant files
janbridley Apr 9, 2024
4903f80
Fix typo
janbridley Apr 10, 2024
a333c5c
Seperate _errors from _templates
janbridley Apr 10, 2024
b0f386b
Clean up docstring return types
janbridley Apr 10, 2024
96acd85
Add PDB cif to test suite
janbridley Apr 10, 2024
a6ebf33
Fix test in test_key_reader
janbridley Apr 10, 2024
f8dbaa3
Clean up patterns.py and add remove_nondelimiting_whitespace
janbridley Apr 10, 2024
b1e0bdd
Update table_reader to use remove_nondelimiting_whitespace
janbridley Apr 10, 2024
51328be
Allow value reader to read mmCIF files
janbridley Apr 10, 2024
06abb57
Update test_table_reader.py
janbridley Apr 10, 2024
98a2201
Remove seperate mmCIF reader
janbridley Apr 10, 2024
93909f8
Add docs for patterns module
janbridley Apr 10, 2024
d4d931b
Fix cast_to_float default value
janbridley Apr 10, 2024
1d86db9
Update docs
janbridley Apr 10, 2024
0528d36
Add documentation for __call__
janbridley Apr 10, 2024
40c7fb8
Update regex_filter param documentation
janbridley Apr 10, 2024
56c1e21
Fix typo
janbridley Apr 10, 2024
853a166
Remove unneeded comment
janbridley Apr 10, 2024
8b19268
Fix default values in docs
janbridley Apr 10, 2024
fd295a8
Fix typo
janbridley Apr 10, 2024
3e5e77c
Minor doc fix
janbridley Apr 10, 2024
ffa59a7
Fix typo
janbridley Apr 10, 2024
7f80005
Remove duplicate Introduction from index
janbridley Apr 10, 2024
1e8c01d
Remove duplicate entries from toc
janbridley Apr 10, 2024
56d80de
Add source for PDB cif
janbridley Apr 10, 2024
5d47d10
Add mmCIF flag to read_cell_params
janbridley Apr 10, 2024
dfbf5ed
Add quickstart.rst
janbridley Apr 10, 2024
28a7025
Fix comment in quickstart
janbridley Apr 10, 2024
e60cd1b
Remove unnecessary line in quickstart
janbridley Apr 10, 2024
6e82566
Fix image path in README.rst
janbridley Apr 11, 2024
a772261
Update regex documentation
janbridley Apr 11, 2024
7d03311
Fix CI
janbridley Apr 11, 2024
1f05fd7
Update __init__.py
janbridley Apr 15, 2024
0ddaa48
Add unitcells module
janbridley Apr 15, 2024
e1616ab
Add documentation links
janbridley Apr 15, 2024
04b19a3
Fix doc file naming
janbridley Apr 15, 2024
451fd8b
Remove resolved TODO
janbridley Apr 15, 2024
bba2849
Add top level description to unitcells
janbridley Apr 15, 2024
8d243ad
Default regex filters to None
janbridley Apr 15, 2024
5fece58
Fix default setting for nondelimiting_whitespace_replacement
janbridley Apr 15, 2024
85b7dff
Remove outdated comment
janbridley Apr 15, 2024
f4aefa7
Fix tests
janbridley Apr 15, 2024
43f0263
Add tests for symmetry operations
janbridley Apr 15, 2024
a713c06
Fix precision issues
janbridley Apr 15, 2024
a0a01cd
Increase string lines threshold
janbridley Apr 15, 2024
8c7f2c0
Remove in-file tests
janbridley Apr 15, 2024
8d5969d
Return unrounded values
janbridley Apr 15, 2024
923ce2c
Add test_extract_unit_cell
janbridley Apr 15, 2024
f96c7a9
Add distance calculation util for uniqueness comparison
janbridley Apr 26, 2024
b124cac
Add function to build basis vector matrix from box
janbridley Apr 26, 2024
cbf17ba
Update unitcell builder and rename to extract_atomic_positions
janbridley Apr 26, 2024
6ab5cd6
Update docstrings
janbridley Apr 26, 2024
e0eccb9
Clarify function naming
janbridley Apr 26, 2024
9bb9b2f
Change space group for IncStrDb_Ccmm.cif to standard format
janbridley Apr 26, 2024
a19b068
Remove unnecessary transpose in basis vector function
janbridley Apr 26, 2024
b3803be
Update unitcell tests to use ase
janbridley Apr 26, 2024
bf532c6
Filter out ase warnings
janbridley Apr 26, 2024
037d5d8
Switch catch_warnings to filterwarnings for python 3.9 compat
janbridley Apr 26, 2024
a1382d3
Add pytest to test requirements
janbridley Apr 27, 2024
b45218d
Fix top of page buttons and add view link
janbridley May 10, 2024
2ab4288
Fix logo on README.rst
janbridley May 10, 2024
e4cbbb8
Merge remote-tracking branch 'origin/main' into feature/supercells
janbridley May 22, 2024
e35ed1b
Merge branch 'main' into feature/supercells
janbridley Jun 3, 2024
bdc832d
Add readable assertion error in unitcells.py
janbridley Jun 10, 2024
c30d23e
Improve assertion error in _safe_eval
janbridley Jun 10, 2024
0632944
Remove unused distance-merge code
janbridley Jun 10, 2024
a023be2
Merge branch 'main' into feature/supercells
janbridley Dec 19, 2024
d65e094
Improve CI resilience
janbridley Dec 19, 2024
ccb13fd
Remove dependabot
janbridley Dec 19, 2024
e562353
Add requirements.txt for py3.6 and py3.7
janbridley Dec 19, 2024
d50b3ee
Update requirements.yaml CI action
janbridley Dec 19, 2024
78fbd68
Remove temporary lines from ci
janbridley Dec 19, 2024
9a2a5e7
Add future-annotations package
janbridley Dec 19, 2024
e0f186b
Fix annotations
janbridley Dec 19, 2024
22b145f
Disable testing on py3.6
janbridley Dec 20, 2024
f046aa0
Update doc requirements
janbridley Dec 20, 2024
3a3dbde
Decapitalize changelog and credits
janbridley Dec 20, 2024
e91767d
Swap tests to us UV
janbridley Dec 20, 2024
77184f6
Fix uv version
janbridley Dec 20, 2024
f3ae2d1
Clean up CI script
janbridley Dec 20, 2024
b85b73b
Activate venv
janbridley Dec 20, 2024
606be0b
Remove setup.py
janbridley Dec 20, 2024
a1be853
Fix CI
janbridley Dec 20, 2024
446f441
Clean up CI
janbridley Dec 20, 2024
cefdb5c
Simplify CI
janbridley Dec 20, 2024
7385f4b
Clean up overview
janbridley Dec 20, 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
Prev Previous commit
Next Next commit
Update unitcell builder and rename to extract_atomic_positions
  • Loading branch information
janbridley committed Apr 26, 2024
commit cbf17ba025569de7a8f28451a6224c7094b5f4fc
88 changes: 78 additions & 10 deletions parsnip/unitcells.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,39 +183,107 @@ def _safe_eval(str_input: str, x: int | float, y: int | float, z: int | float):
return eval(safe_string, {"__builtins__": {}}, {}) # noqa: S307


def extract_unit_cell(filename: str, n_decimal_places: int = 4):
"""Return a complete unit cell from a CIF file in fractional coordinates.
def _write_debug_output(unique_indices, unique_counts, pos, check="Initial"):
print(f"{check} uniqueness check:")
if len(unique_indices) == len(pos):
print("... all points are unique (within tolerance).")
else:
print("(duplicate point, number of occurences)")
[
print(pt, count)
for pt, count in zip(pos[unique_indices], unique_counts)
if count > 1
]

print()


def extract_atomic_positions(
filename: str,
fractional: bool = True,
n_decimal_places: int = 4,
verbose: bool = False,
):
"""Reconstruct atomic positions from Wyckoff sites and symmetry operations.

.. warning::

Reconstructing positions requires several floating point calculations that can
be impacted by low-precision data in CIF files. Typically, at least four decimal
places are required to accurately reconstruct complicated unit cells: less
precision than this can yield cells with duplicate or missing positions.

Args:
filename (str): The name of the .cif file to be parsed.
fractional (bool, optional):
Whether to return fractional or absolute coordinates.
Default value = ``True``
n_decimal_places (int, optional):
The number of decimal places to round each position to for the uniqueness
comparison. Because CIF files only store a few decimal places, a relatively
low value is required for good results. 4 decimal places is usually enough
to differentiate every unique position.
comparison. Values higher than 4 may not work for all CIF files.
Default value = ``4``
verbose (bool, optional):
Whether to print debug information about the uniqueness checks.
Default value = ``False``

Returns:
:math:`(N, 3)` :class:`numpy.ndarray[np.float32]`:
The full unit cell of the crystal structure.
"""
fractional_positions = read_fractional_positions(filename=filename)

# Read the cell params and conver to a matrix of basis vectors
cell = read_cell_params(filename, degrees=False, mmcif=False)
cell_matrix = _matrix_from_lengths_and_angles(*cell)

symops = read_symmetry_operations(filename)
symops_str = np.array2string(
symops,
separator=",", # Place a comma after each line in the array. Required to eval
separator=",", # Place a comma after each line in the array. Required for eval
threshold=np.inf, # Ensure that every line is included in the string
floatmode="unique", # Ensures strings can uniquely represent each float number
)

all_frac_positions = [_safe_eval(symops_str, *xyz) for xyz in fractional_positions]

pos = np.vstack(all_frac_positions)
pos %= 1 # Wrap particles into the box

# Filter unique points. This takese some time, but makes the method faster overall
_, unique_indices, unique_counts = np.unique(
pos.round(n_decimal_places), return_index=True, return_counts=True, axis=0
)
Comment on lines +252 to +254

Choose a reason for hiding this comment

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

Would it be possible to use tolerance instead of rounding here? This is OK, but rounding doesn't give you precise control over the tolerance you wish to apply....

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I will come up with a solution for this - it's a shame it's not implemented in Numpy general, as this is a problem I run into frequently.


if verbose:
_write_debug_output(unique_indices, unique_counts, pos, check="Initial")

# Wrap particles into the box
pos %= 1
# Remove initial duplicates, then map to real space for a second check
pos = pos[unique_indices]
real_space_positions = pos @ cell_matrix

# TODO: add "fractional" flag?
_, unique_indices, unique_counts = np.unique(
real_space_positions.round(n_decimal_places),
return_index=True,
return_counts=True,
axis=0,
)

if verbose:
_write_debug_output(unique_indices, unique_counts, pos, check="Secondary")

"""
# This code allows for parity with Gemmi - however, the results are effectively
# identical to the code above. This could be re-enabled in the future if desired.
if not np.isclose(merge_dist,0):
dists,i_inds,j_inds = _get_distances(real_space_positions[unique_indices])

# Now, get the positions that are less than merge_dist apart and remove them
overlapping_point_indices = np.vstack([i_inds,j_inds])[:, dists<merge_dist**2].T
pos = np.delete(pos, overlapping_point_indices[:,1],axis=0)
if verbose:
print("Tertiary uniqueness check:")
print(f"... {len(overlapping_point_indices)} points removed")
real_space_positions = pos@cell_matrix
"""

return pos[np.unique(pos.round(n_decimal_places), return_index=True, axis=0)[1]]
return pos[unique_indices] if fractional else real_space_positions[unique_indices]