Skip to content

Commit aff2867

Browse files
committed
add particle_rugosity
1 parent bd950f0 commit aff2867

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Particle Rugosity
2+
3+
## Summary
4+
Simulates the particle shape of the given crystal structure using BFDH mophology
5+
prediction, then calculates the particle rugosity by determining the rugosity
6+
of the facets and calculating the weighted average (by facet area).
7+
8+
### Relevance
9+
Rugosity is considered to be a factor in nucleation, with rougher crystal surfaces
10+
having higher energies and being generally less stable. This property has been used
11+
in rationalizing the relative stability or probability of forming one polymorph
12+
(or putative crystal structure from Crystal Structure Prediction, CSP) over another.
13+
14+
Using a protocol similar to that reported by [Cruz-Cabeza and colleagues](https://doi.org/10.1002/anie.202006939) this script
15+
takes a crystal structure or refcode as an argument and will use the CCDC BFDH
16+
morphology module to simulate the predicted particle shape. The facet hkl planes are
17+
then obtained and the rugosity of these planes is calculated using the [CCDC rugosity function](https://downloads.ccdc.cam.ac.uk/documentation/API/descriptive_docs/particle.html) (including a scan of
18+
different off-sets from the origin to identify the minimum rugosity of that crystal
19+
plane). Finally, the total particle rugosity is calculated by weighted average
20+
according to the facet surface areas.
21+
22+
## Requirements
23+
24+
- Tested with CSD Python API version 3.7.9 on Linux and Windows
25+
- ccdc.particle
26+
- ccdc.morphology
27+
28+
## Licensing Requirements
29+
30+
- CSD-Core
31+
32+
## Instructions on Running
33+
### Linux command line
34+
- load the CSD Python API Miniconda environment
35+
- call Python to read the script, add the crystal structure refcode or filename (local file)
36+
~~~
37+
$ python particle_rugosity.py AABHTZ
38+
The crystal structure AABHTZ has been loaded
39+
Calculating particle rugosity ...
40+
AABHTZ particle rugosity: 1.5073781143188552
41+
~~~
42+
OR
43+
~~~
44+
$ python particle_rugosity.py AABHTZ.cif
45+
~~~
46+
- results are printed and can be redirected to be saved in an output file
47+
~~~
48+
$ python particle_rugosity.py AABHTZ > AABHTZ_rugosity.out
49+
~~~
50+
51+
### Windows CSD Python API
52+
- move the particle\_rugostiy.py file to the CCDC\Python\_API\_(year)\ folder
53+
- to determine where this is on your computer, start the CSD Python API and enter the following commands
54+
~~~
55+
>>> import os
56+
>>> wd = os.getcwd()
57+
>>> print(wd)
58+
C:\Program Files\CCDC\Python_API_2022\
59+
~~~
60+
the last line is the folder location where you need to move the particle\_rugostiy.py file
61+
- now the script can be run in the CSD Python API to calculate the rugosity of any CSD entry using:
62+
~~~
63+
>>> import sys
64+
>>> import subprocess
65+
>>> subprocess.call([sys.executable, 'particle_rugosity.py', 'AABHTZ'])
66+
The crystal structure AABHTZ has been loaded
67+
Calculating particle rugosity ...
68+
AABHTZ particle rugosity: 1.5073781143188552
69+
~~~
70+
OR
71+
- if you want to run your own crystal structures, make a folder (eg. rugosity_calc) in Python_API_(year), and add your
72+
crystal structure file to that folder
73+
- modify the argument to include the file path
74+
~~~
75+
>>> subprocess.call([sys.executable, 'particle_rugosity.py', 'rugosity_calc/AABHTZ.cif'])
76+
The crystal structure rugosity_calc/AABHTZ.cif has been loaded
77+
Calculating particle rugosity ...
78+
AABHTZ particle rugosity: 1.5073781143188552
79+
~~~
80+
81+
## Author
82+
83+
_R. Alex Mayo_ 2023
84+
85+
> For feedback or to report any issues please contact [support@ccdc.cam.ac.uk](mailto:support@ccdc.cam.ac.uk)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# script for calculating the particle rugosity for a given crystal structure (.cif in local working directory, or refcode of a CSD entry)
2+
# requires a CCDC license, and loading of the CSD-python miniconda environment if run from Linux command line
3+
4+
# import ccdc modules
5+
import ccdc
6+
from ccdc.io import CrystalReader
7+
from ccdc import particle
8+
from ccdc.particle import Surface
9+
from ccdc import morphology
10+
from ccdc.morphology import BFDHMorphology
11+
12+
def particle_rugosity(crystal):
13+
# load structure, either (1) crystal structure file in working directory, or
14+
# (2) CSD refcode
15+
head, sep, tail = crystal.partition('.')
16+
if sep == '.':
17+
# agrument is crystal structure file
18+
xname = crystal
19+
xtal1 = CrystalReader(xname)
20+
xtal = xtal1[0]
21+
xtal1.close
22+
else:
23+
# agrument is a CSD refcode
24+
xname = crystal
25+
xtal = CrystalReader('CSD').crystal(xname)
26+
27+
print(f"The crystal structure {crystal} has been loaded")
28+
print("Calculating particle rugosity ...")
29+
# run BFDH morphology to determine predicted particle surface area = hkl planes, and d-spacing of the planes
30+
morphology = BFDHMorphology(xtal)
31+
facets = morphology.facets
32+
f = facets[0]
33+
all_hkl = [f.miller_indices.hkl for f in facets]
34+
all_mi = [f.miller_indices for f in facets]
35+
facets_relA = [morphology.relative_area(mi) for mi in all_mi]
36+
all_d_hkl = [f.miller_indices.d_spacing for f in facets]
37+
num_face = len(all_d_hkl)
38+
# generate surfaces and record rugosity, weigh by particle surface area
39+
w_part_rug = []
40+
for i in range(num_face):
41+
hkl = all_hkl[i]
42+
rug_list = []
43+
# check rugosity of crystal plane at 0, 0.25, 0.5, and 0.75 offset from origin
44+
for split in range(1,5):
45+
os = all_d_hkl[i] / split
46+
surface = Surface(xtal, hkl, offset=os)
47+
rug_list.append(surface.descriptors.rugosity)
48+
49+
# only take the minimum rugosity value (from all offset calculations) for each hkl
50+
rug = min(rug_list)
51+
w_surf_rug = rug * facets_relA[i]
52+
w_part_rug.append(w_surf_rug)
53+
54+
# sum weighted rugosity values and print total particle rugosity
55+
tot_rug = sum(w_part_rug)
56+
print(f'{crystal} particle rugosity: ',tot_rug)
57+
58+
# ================================
59+
# argument parser
60+
import argparse
61+
parser = argparse.ArgumentParser()
62+
parser.add_argument("input_x")
63+
args = parser.parse_args()
64+
crystal = args.input_x
65+
66+
# run code
67+
particle_rugosity(crystal)
68+

0 commit comments

Comments
 (0)