Skip to content

Commit

Permalink
Merge pull request #15 from jennyfothergill/feat/plot-with-units
Browse files Browse the repository at this point in the history
Add plot function to diffractometer class with units along axis
  • Loading branch information
jennyfothergill authored Feb 16, 2022
2 parents 1bd5ff8 + 89543ef commit 4f5e50e
Show file tree
Hide file tree
Showing 12 changed files with 418 additions and 150 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ __pycache__/
*.gsd
*.txt
*.png
to_delete
scratch

# Compiled python modules.
*.pyc
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ cd GIXStapose
conda env create -f environment.yml;
conda activate gixstapose
```
3. With the environment active, install this package
```
pip install .
```

### Usage
To run a simple cubic example:
Expand Down
119 changes: 93 additions & 26 deletions examples/Figure_Example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
"import PIL\n",
"import matplotlib.pyplot as plt\n",
"from fresnel import camera, pathtrace\n",
"import mbuild as mb\n",
"\n",
"from gixstapose.draw_scene import get_scene\n",
"from gixstapose.draw_scene import get_scene, get_info\n",
"from gixstapose.diffractometer import Diffractometer"
]
},
Expand All @@ -45,9 +44,7 @@
"metadata": {},
"outputs": [],
"source": [
"scene, [N, types, typeids, positions, N_bonds, bonds, box] = get_scene(\n",
" \"../gixstapose/data/sc10.pdb\"\n",
")"
"scene, info = get_scene(\"../gixstapose/data/sc10.pdb\")"
]
},
{
Expand Down Expand Up @@ -121,13 +118,10 @@
"metadata": {},
"outputs": [],
"source": [
"d = Diffractometer()\n",
"d.load(positions, box)\n",
"dp = d.diffract_from_camera(cam)\n",
"fig,ax = plt.subplots(figsize=(10,10))\n",
"ax.axis(\"off\")\n",
"ax.set_axis_off()\n",
"ax.imshow(dp, cmap=\"jet\");"
"d = Diffractometer(length_scale=1.0)\n",
"d.load(info[\"positions\"], info[\"box\"])\n",
"d.diffract_from_camera(cam)\n",
"fig, ax = d.plot()"
]
},
{
Expand All @@ -150,9 +144,11 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally let's look at a messy example using real simulation data. This xml file was taken from [https://doi.org/10.18122/cme_lab/4/boisestate](https://doi.org/10.18122/cme_lab/4/boisestate).\n",
"Finally let's look at a messy example using real simulation data. The original xml file was taken from [https://doi.org/10.18122/cme_lab/4/boisestate](https://doi.org/10.18122/cme_lab/4/boisestate).\n",
"\n",
"The original file can be found in p3ht_data/1000_oligomers/crystallinities/crystalline.xml. (The file was converted from an xml to a mol2 and reduced to contain only the backbone carbons (type CA) so it would load more quickly.) This is from one of our labs united-atom simulations of organic photovoltaic polymers, specifically [P3HT](http://gisaxs.com/index.php/Material:P3HT). Even with these simplifications, it is still a large file, so the following cells may be a little slow."
"The original file can be found in p3ht_data/1000_oligomers/crystallinities/crystalline.xml. The file was converted from an xml to a gsd using [cmeutils](https://github.com/cmelab/cmeutils) [xml_to_gsd](https://github.com/cmelab/cmeutils/blob/8e33350630891cde89c9ba82a9adc682407c320f/cmeutils/gsd_utils.py#L192) function, and reduced to contain only the backbone carbons (type CA) using [snap_delete_types](https://github.com/cmelab/cmeutils/blob/8e33350630891cde89c9ba82a9adc682407c320f/cmeutils/gsd_utils.py#L141) so it would load more quickly. \n",
"\n",
"This is from one of our united-atom simulations of organic photovoltaic polymers, specifically [P3HT](http://gisaxs.com/index.php/Material:P3HT). Even with these simplifications, it still contains 60,000 particles, so the following cells may be a little slow."
]
},
{
Expand All @@ -161,7 +157,7 @@
"metadata": {},
"outputs": [],
"source": [
"p3ht_file = \"../gixstapose/data/crystalline_CAonly.mol2\""
"p3ht_file = \"../gixstapose/data/crystalline_CAonly.gsd\""
]
},
{
Expand All @@ -181,7 +177,7 @@
" position = [2.892, 5.120, -0.830],\n",
" look_at = [-0.797, 0.604, 0.862],\n",
" up = [-0.733, 0.390, -0.557],\n",
" height = 7.307\n",
" height = 170\n",
")"
]
},
Expand All @@ -198,9 +194,7 @@
"metadata": {},
"outputs": [],
"source": [
"p3ht_scene, [N, types, typeids, positions, N_bonds, bonds, box] = get_scene(\n",
" p3ht_file, color={\"CA\": \"gray\"}\n",
")\n",
"p3ht_scene, info = get_scene(p3ht_file, color={\"CA\": \"gray\"}, scale=4)\n",
"p3ht_scene.camera = cam\n",
"p3ht_output = pathtrace(p3ht_scene, light_samples=40, w=600, h=600)\n",
"p3ht_output"
Expand All @@ -210,7 +204,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"At this particular angle we'll draw your attention to parallel stripes of gray separated by black shadowy regions: These stripes are \"lamellae\" and are a periodic feature that should be measurable with the GIXStapose diffractometer. (Reminder! I used GIXStapose to find an orientation with measurable lamellar peaks and saved its camera orientation so we *could* return to this precise orientation!)"
"At this particular angle we'll draw your attention to parallel stripes of gray separated by black shadowy regions: These stripes are \"lamellae\" and are a periodic feature that should be measurable with the GIXStapose diffractometer. (Reminder! I used GIXStapose GUI to find an orientation with measurable lamellar peaks and saved its camera orientation so we *could* return to this precise orientation!)"
]
},
{
Expand All @@ -219,13 +213,10 @@
"metadata": {},
"outputs": [],
"source": [
"d = Diffractometer()\n",
"d.load(positions, box)\n",
"d = Diffractometer(length_scale=1)\n",
"d.load(info[\"positions\"], info[\"box\"])\n",
"dp = d.diffract_from_camera(cam)\n",
"fig,ax = plt.subplots(figsize=(10,10))\n",
"ax.axis(\"off\")\n",
"ax.set_axis_off()\n",
"ax.imshow(dp, cmap=\"jet\");"
"fig, ax = d.plot()"
]
},
{
Expand All @@ -235,6 +226,82 @@
"Aw yeah, just look at that classic lamellar structure! The reflections of the (100) and (200) crystallographic planes are clearly visibile, with a hint of (300)! In this diffraction pattern, the wave vectors pointing to these yellow/green peak centers can be used to derive average lamellar spacings that would be a mess to deduce from the direct visualization. This example showcases how looking at chemical structures through the diffraction lens *first* can identify periodic features that may not be immediately visible to the eye. Once we know a periodic feature exists, we can pull up the chemical structure visualization and look for features at the expected length scales. We can also use this orientation as a reference point to generate a sequence of rotations that reveal other structures (e.g., for you P3HT experts, an orientation that more clearly reveals the spacing of the pi-pi stacking of the P3HT backbones)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, if you want to get the reciprocal space values of the peaks in your diffraction pattern, we provide an interactive class called `PeakLabeller` you can use. Sometimes the interactive backends of matplotlib are a little tricky, so you may need to restart your kernel and reload some information."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib qt5"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# This cell will reload necessary information if needed\n",
"import matplotlib.pyplot as plt\n",
"\n",
"from fresnel import camera\n",
"\n",
"from gixstapose.draw_scene import get_info\n",
"from gixstapose.diffractometer import Diffractometer, PeakLabeller\n",
"\n",
"\n",
"p3ht_file = \"../gixstapose/data/crystalline_CAonly.gsd\"\n",
"info = get_info(p3ht_file)\n",
"\n",
"cam = camera.Orthographic(\n",
" position = [2.892, 5.120, -0.830],\n",
" look_at = [-0.797, 0.604, 0.862],\n",
" up = [-0.733, 0.390, -0.557],\n",
" height = 170\n",
")\n",
"\n",
"d = Diffractometer(length_scale=1)\n",
"d.load(info[\"positions\"], info[\"box\"])\n",
"dp = d.diffract_from_camera(cam)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig, ax = d.plot()\n",
"\n",
"PeakLabeller(ax)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"peaks = [0.057, 0.290]\n",
"for peak in peaks:\n",
" print(f\"The peak at {peak} 1/Å corresponds to a periodic spacing of {1/peak:.2f} Å.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The figure below was created using `PeakLabeller`. We can see that these periodic distances are reasonable for the lamellar spacing (\\~17 Å) and pi-stacking (\\~4 Å) and agree with [previously reported values](https://doi.org/10.1016/j.orgel.2013.02.028).\n",
"![labelled peaks](../gixstapose/data/labelledpeaks.png)"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
16 changes: 16 additions & 0 deletions examples/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: gixstapose-ex
channels:
- conda-forge
dependencies:
- fresnel>=0.13
- gsd>=2.4
- jupyter
- matplotlib>=3.4
- mbuild>=0.13
- numpy>=1.21
- openbabel=3.1.1
- pillow>=8.3
- pip>=21
- py3Dmol>=1.7
- python=3.8
- rowan>=1.3
Binary file added gixstapose/data/crystalline_CAonly.gsd
Binary file not shown.
Binary file added gixstapose/data/labelledpeaks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4f5e50e

Please sign in to comment.