Skip to content

Commit 5034f84

Browse files
Merge pull request #25 from ramayo223/main
add particle_rugosity
2 parents bd950f0 + 0ceff2f commit 5034f84

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

scripts/ReadMe.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ This folder contains scripts submitted by users or CCDC scientists for anyone to
2626
### Create GAUSSIAN Input
2727
- Create GAUSSIAN input file (`.gjf`) for a given CSD refcode or `.mol2` file.
2828

29+
### Particle Rugosity
30+
- Calculates the simulated BFDH particle rugosity weighted by facet area.
31+
2932
## Tips
3033
A section for top tips in using the repository and GitHub.
3134
### Searching tips:
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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 offsets 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, CSD-Particle
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.507
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+
>>> from particle_rugosity import particle_rugosity
64+
>>> particle_rugosity('AABHTZ')
65+
The crystal structure AABHTZ has been loaded
66+
Calculating particle rugosity ...
67+
AABHTZ particle rugosity: 1.507
68+
~~~
69+
OR
70+
- if you want to run your own crystal structures, make a folder (eg. rugosity_calc) in Python_API_(year), and add your
71+
crystal structure file to that folder
72+
- modify the argument to include the file path
73+
~~~
74+
>>> particle_rugosity('rugosity_calc/AABHTZ.cif')
75+
The crystal structure rugosity_calc/AABHTZ.cif has been loaded
76+
Calculating particle rugosity ...
77+
rugosity_calc/AABHTZ.cif particle rugosity: 1.507
78+
~~~
79+
80+
## Author
81+
82+
_R. Alex Mayo_ 2023
83+
84+
> For feedback or to report any issues please contact [support@ccdc.cam.ac.uk](mailto:support@ccdc.cam.ac.uk)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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 os as opsys
6+
import argparse
7+
from ccdc.io import CrystalReader
8+
from ccdc.particle import Surface
9+
from ccdc.morphology import BFDHMorphology
10+
11+
def particle_rugosity(xname):
12+
# xname is a string, either refcode (eg: 'AABHTZ') or filename (eg: 'AABHTZ.cif')
13+
# load structure, either (1) crystal structure file in working directory, or
14+
# (2) CSD refcode
15+
if opsys.path.isfile(xname):
16+
try:
17+
# agrument is crystal structure file
18+
xtal1 = CrystalReader(xname)
19+
xtal = xtal1[0]
20+
xtal1.close
21+
except:
22+
print("Error in reading crystal structure input.\nPlease enter a CSD refcode or provide the path to your crystal structure file")
23+
input('Press ENTER to exit')
24+
quit()
25+
else:
26+
try:
27+
# agrument is a CSD refcode
28+
xtal = CrystalReader('CSD').crystal(xname)
29+
except:
30+
print("Error in reading crystal structure input.\nPlease enter a CSD refcode or provide the path to your crystal structure file")
31+
input('Press ENTER to exit')
32+
quit()
33+
34+
print(f"The crystal structure {xname} has been loaded")
35+
print("Calculating particle rugosity ...")
36+
37+
# run BFDH morphology to determine predicted particle surface area = hkl planes, and d-spacing of the planes
38+
morphology = BFDHMorphology(xtal)
39+
facets = morphology.facets
40+
f = facets[0]
41+
all_hkl = [f.miller_indices.hkl for f in facets]
42+
all_mi = [f.miller_indices for f in facets]
43+
facets_relA = [morphology.relative_area(mi) for mi in all_mi]
44+
all_d_hkl = [f.miller_indices.d_spacing for f in facets]
45+
num_face = len(all_d_hkl)
46+
47+
# generate surfaces and record rugosity, weigh by particle surface area
48+
w_part_rug = []
49+
for i in range(num_face):
50+
hkl = all_hkl[i]
51+
rug_list = []
52+
53+
# check rugosity of crystal plane at 0, 0.25, 0.5, and 0.75 offset from origin
54+
for split in range(1,5):
55+
os = all_d_hkl[i] / split
56+
surface = Surface(xtal, hkl, offset=os)
57+
rug_list.append(surface.descriptors.rugosity)
58+
59+
# only take the minimum rugosity value (from all offset calculations) for each hkl
60+
rug = min(rug_list)
61+
w_surf_rug = rug * facets_relA[i]
62+
w_part_rug.append(w_surf_rug)
63+
64+
# sum weighted rugosity values and print total particle rugosity
65+
tot_rug = sum(w_part_rug)
66+
print(f'{xname} particle rugosity: ',round(tot_rug, 3))
67+
68+
# ================================
69+
if __name__=='__main__':
70+
parser = argparse.ArgumentParser()
71+
parser.add_argument("input_x")
72+
args = parser.parse_args()
73+
crystal = args.input_x
74+
75+
# run code
76+
particle_rugosity(crystal)
77+

0 commit comments

Comments
 (0)