Skip to content

Commit 935caef

Browse files
authored
Merge pull request #52 from ccdc-opensource/shape_classification
November 2023 Webinar scripts
2 parents 600305c + 0712db3 commit 935caef

File tree

4 files changed

+206
-0
lines changed

4 files changed

+206
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Working with morphologies and CSD-Particle
2+
3+
This is a collection of scripts from the November 2023 CCDC Webinar on crystal morphologies, presented by Dr Andrew G.
4+
P. Maloney.
5+
6+
## Contents
7+
8+
This folder contains the following scripts:
9+
10+
- `calculate_morphologies_tabulate_input.py`
11+
Runs a calculation of BFDH morphology and VisualHabit morphology for `IBPRAC18` (ibuprofen), printing a table of
12+
facet properties.
13+
- `exploring_surface_properties.py`
14+
Calculates the VisualHabit morphology of `IBPRAC18` (ibuprofen) and descriptors for the (100) surface. Also calculates
15+
particle rugosity.
16+
- `morphology_plot.py`
17+
Contains a function to generate a 3D plot of a crystal morphology using Matplotlib. Running the script will plot the
18+
BFDH morphology of `IBPRAC18` (ibuprofen).
19+
20+
## Requirements
21+
22+
All of the modules required to run these scripts are available in the miniconda environment installed with the CSD
23+
Python API.
24+
25+
## Licensing requirements
26+
27+
- CSD-Core, CSD-Particle
28+
29+
## Usage
30+
31+
Each script can be run independently from the command line:
32+
33+
`python script_name.py`
34+
35+
### Author
36+
37+
Pietro Sacchi
38+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#
2+
# This script can be used for any purpose without limitation subject to the
3+
# conditions at http://www.ccdc.cam.ac.uk/Community/Pages/Licences/v2.aspx
4+
#
5+
# This permission notice and the following statement of attribution must be
6+
# included in all copies or substantial portions of this script.
7+
#
8+
9+
"""
10+
This script runs a morphology calculation and outputs the facet properties.
11+
"""
12+
import pandas as pd
13+
from ccdc.io import EntryReader
14+
from ccdc.morphology import BFDHMorphology
15+
16+
csd = EntryReader('CSD')
17+
ibuprofen = csd.crystal("IBPRAC18")
18+
bfdh_morphology = BFDHMorphology(ibuprofen)
19+
20+
bfdh_facet_data = [[f.miller_indices.hkl, round(f.area, 3)] for f in bfdh_morphology.facets]
21+
22+
print()
23+
print("BFDH Data:")
24+
print(pd.DataFrame(bfdh_facet_data, columns=["Miller Index", "Facet Area"]))
25+
26+
from ccdc.morphology import VisualHabit
27+
28+
visualhabit_settings = VisualHabit.Settings()
29+
visualhabit_settings.potential = 'dreidingII'
30+
vh_results = VisualHabit().calculate(ibuprofen)
31+
vh_morphology = vh_results.morphology
32+
33+
vh_facet_data = [[f.miller_indices.hkl, f.area, f.attachment_energy] for f in vh_morphology.facets]
34+
35+
print()
36+
print("VisualHabit Data:")
37+
print(pd.DataFrame(vh_facet_data, columns=["Miller Index", "Facet Area", "Attachment Energy"]))
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#
2+
# This script can be used for any purpose without limitation subject to the
3+
# conditions at http://www.ccdc.cam.ac.uk/Community/Pages/Licences/v2.aspx
4+
#
5+
# This permission notice and the following statement of attribution must be
6+
# included in all copies or substantial portions of this script.
7+
#
8+
9+
"""
10+
This script shows a few uses of the CSD Particle tools available.
11+
"""
12+
import pandas as pd
13+
from ccdc.io import EntryReader
14+
from ccdc.particle import Surface
15+
from ccdc.morphology import VisualHabit
16+
17+
csd = EntryReader('CSD')
18+
ibuprofen = csd.crystal("IBPRAC18")
19+
20+
visualhabit_settings = VisualHabit.Settings()
21+
visualhabit_settings.potential = 'dreidingII'
22+
vh_results = VisualHabit().calculate(ibuprofen)
23+
vh_morphology = vh_results.morphology
24+
25+
# Surface topology
26+
ibuprofen_100 = Surface(ibuprofen, (1, 0, 0))
27+
print()
28+
print("Ibuprofen (100) topology descriptors (no offset):")
29+
print(ibuprofen_100.descriptors.rugosity)
30+
31+
ibuprofen_100 = Surface(ibuprofen, (1, 0, 0), offset=4.308)
32+
surface_topology = [[(1, 0, 0),
33+
ibuprofen_100.descriptors.rugosity,
34+
ibuprofen_100.descriptors.rmsd,
35+
ibuprofen_100.descriptors.skewness,
36+
ibuprofen_100.descriptors.kurtosis]]
37+
38+
print()
39+
print("Ibuprofen (100) topology descriptors:")
40+
print(pd.DataFrame(surface_topology, columns=["Facet", "Rugosity", "RMSD", "Skewness", "Kurtosis"]))
41+
42+
# Surface chemistry
43+
surface_chemistry = [[(1, 0, 0),
44+
ibuprofen_100.descriptors.hb_donors,
45+
ibuprofen_100.descriptors.hb_acceptors,
46+
ibuprofen_100.descriptors.aromatic_bonds]]
47+
48+
print()
49+
print("Ibuprofen (100) surface chemistry descriptors:")
50+
print(pd.DataFrame(surface_chemistry,
51+
columns=["Facet", "Density, HB Donors", "Density, HB Acceptors", "Density, Aromatic Bonds"]))
52+
53+
# Average surface properties
54+
facet_rugosity_data = []
55+
for facet in vh_morphology.facets:
56+
hkl = facet.miller_indices.hkl
57+
relative_area = round(vh_morphology.relative_area(facet.miller_indices), 3)
58+
rugosity = Surface(ibuprofen, facet.miller_indices.hkl).descriptors.rugosity
59+
weighted_rugosity = relative_area * rugosity
60+
facet_rugosity_data.append([hkl, relative_area, rugosity, weighted_rugosity])
61+
62+
facet_rugosities = pd.DataFrame(facet_rugosity_data,
63+
columns=["Facet", "Relative Area", "Rugosity", "Weighted Rugosity"])
64+
print()
65+
print("Facet rugosities:")
66+
print(facet_rugosities)
67+
68+
# Particle rugosity
69+
import morphology_plot as plotter
70+
71+
print()
72+
print("Weighted rugosity:")
73+
print(round(facet_rugosities["Weighted Rugosity"].sum(), 3))
74+
plotter.generate_morphology_plot(vh_morphology, labels=list(facet_rugosities["Rugosity"]))
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import matplotlib
2+
# matplotlib.use('Agg')
3+
import matplotlib.pyplot as plt
4+
from mpl_toolkits.mplot3d import Axes3D
5+
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
6+
7+
"""
8+
Script to create a 3D plot of a crystal morphology.
9+
"""
10+
11+
12+
def generate_morphology_plot(morphology, labels=None):
13+
fig = plt.figure(figsize=(10., 10.)) # 3D graph instance
14+
ax = fig.add_subplot(111, projection='3d') # 3D Axes
15+
_ = ax.set_xlim3d(-15, 15) # Set the axes limits
16+
_ = ax.set_ylim3d(-15, 15)
17+
_ = ax.set_zlim3d(-15, 15)
18+
_ = ax.grid(False) # To hide the gridlines
19+
_ = plt.axis('off') # To hide the axes
20+
for i, facet in enumerate(morphology.facets):
21+
for edge in facet.edges:
22+
Axes3D.plot(ax,
23+
[coord[0] for coord in edge], # The x coordinates
24+
[coord[1] for coord in edge], # The y coordinates
25+
[coord[2] for coord in edge], # The z coordinates
26+
c='black',
27+
linewidth=1.5)
28+
for edge in facet.edges:
29+
vertices = [(edge[0], edge[1], facet.centre_of_geometry)]
30+
Axes3D.add_collection3d(ax, Poly3DCollection(vertices, color='blue', linewidth=0, alpha=0.3))
31+
if labels:
32+
ax.text(facet.centre_of_geometry[0], facet.centre_of_geometry[1], facet.centre_of_geometry[2],
33+
''' {}
34+
{}'''.format(facet.miller_indices.hkl, labels[i]),
35+
color='black')
36+
else:
37+
ax.text(facet.centre_of_geometry[0], facet.centre_of_geometry[1], facet.centre_of_geometry[2],
38+
''' {}
39+
{}'''.format(facet.miller_indices.hkl, round(morphology.relative_area(facet.miller_indices), 3)),
40+
color='black')
41+
42+
ax.scatter(facet.centre_of_geometry[0],
43+
facet.centre_of_geometry[1],
44+
facet.centre_of_geometry[2],
45+
s=10,
46+
color='black')
47+
plt.show()
48+
49+
50+
if __name__ == "__main__":
51+
from ccdc.io import EntryReader
52+
from ccdc.morphology import BFDHMorphology
53+
54+
csd = EntryReader('CSD')
55+
ibuprofen = csd.crystal("IBPRAC18")
56+
bfdh_morphology = BFDHMorphology(ibuprofen)
57+
generate_morphology_plot(bfdh_morphology)

0 commit comments

Comments
 (0)