-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
55fbe41
commit aca6b39
Showing
1 changed file
with
367 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,367 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# 12 - Using View Structures:\n", | ||
"\n", | ||
"\n", | ||
"### In this tutorial we will walk through many examples of how and what to use view structures for, and is meant as a hightlight of this function's ability.\n", | ||
"\n", | ||
"If you do not see a potential capability please let the developers know of your desire on github!!\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from architector import (view_structures,\n", | ||
" build_complex,\n", | ||
" convert_io_molecule)\n", | ||
"from architector.io_calc import CalcExecutor # Run XTB calculations\n", | ||
"from architector.io_samplers import random_sampler # Create distortions\n", | ||
"from architector.vibrations_free_energy import vibration_analysis # Vibrational analysis to get normal modes\n", | ||
"import architector.arch_context_manage as arch_context_manage # Temporary directory generation\n", | ||
"from ase.vibrations import Vibrations # ASE implemenation of vibrational analysis\n", | ||
"import numpy as np " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Even before running architector, view_structures can be used to visualize SMILES strings!\n", | ||
"# In the background, openbabel is used to build these in 3D\n", | ||
"view_structures(['C','CN','COC','CC=CC'])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# To start from Architector, let's build complexes to visualize\n", | ||
"inp = {'core':{'metal':'Fe','coreCN':6},\n", | ||
" 'ligands':['bipy']*2+['chloride']+['water'],\n", | ||
" 'parameters':{'skip_duplicate_tests':True,\n", | ||
" 'assemble_method':'UFF',\n", | ||
" 'full_method':'UFF',\n", | ||
" 'relax':True}}\n", | ||
"out = build_complex(inp)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# At it's base, view structures can be called on any number of types of structures.\n", | ||
"# On Architector output dictionaries (e.g. out) it will pull out the mol2string fields to visualize.\n", | ||
"# These are sorted by energy by default\n", | ||
"view_structures(out)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# You can play with the size/shape of viewer grids:\n", | ||
"view_structures(out,\n", | ||
" columns=2, # Check the number of columns the viewer will use.\n", | ||
" w=400, # Change the size of each viewer width in pixels. Default is 200\n", | ||
" h=400 # Change the size of each viewer height in pixels. Default is 200\n", | ||
" )\n", | ||
"# This will thus make a 2X2 grid with larger versions of the molecules viewed." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Now, we will pull out just the mol2strings to highlight other view_structures functionality\n", | ||
"mol_list = [val['mol2string'] for key,val in out.items()]\n", | ||
"energies = [val['energy'] for key,val in out.items()] # Pull out the energies\n", | ||
"energy_labels = ['{0:.2f}'.format(x) for x in (np.array(energies)-min(energies))] # Format and make the energies relative to minimum energy" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# We can now add the energies of the structures as labels.\n", | ||
"view_structures(mol_list,\n", | ||
" labels=energy_labels # Add labels to the centroid of the molecules with the relative energies\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# You can also add arbitrary strings or numbers as labels\n", | ||
"view_structures(mol_list,\n", | ||
" labels=np.arange(len(mol_list)) # Add labels corresponding to the indices of the structures\n", | ||
" )\n", | ||
"view_structures(mol_list,\n", | ||
" labels=['zero','one','two',\n", | ||
" 'three','four','five'][:len(mol_list)] # Add labels up to the number of structures produced\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Interatomic distances can also be visualized\n", | ||
"view_structures(mol_list,\n", | ||
" vis_distances=True)\n", | ||
"# For much more parameters on how to edit and tweak visualization of \n", | ||
"# interatomic distances please see tutorial 11-Distance_Analysis.ipynb!" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Similar to labels, you can request to label the indices in each structure.\n", | ||
"view_structures(mol_list,\n", | ||
" w=400, # Make the viewer larger\n", | ||
" h=400, # Make the viewer larger\n", | ||
" columns=2, # Switch to two columns\n", | ||
" labelinds=True, # Label the indices of the atoms in the molecule\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# For simplicity, we can select a single structure to view the indices of the atoms in the molecule\n", | ||
"mol = convert_io_molecule(mol_list[1])\n", | ||
"# Similar to labels, you can pass a list of values or strings to visualize on top of the indices.\n", | ||
"view_structures(mol,\n", | ||
" w=400, # Make the viewer larger\n", | ||
" h=400, # Make the viewer larger\n", | ||
" labelinds=(np.arange(len(mol.ase_atoms))/10).tolist(), # Label the indices of the atoms in the molecule\n", | ||
" )\n", | ||
"# Note that this is useful for visualizing charges\n", | ||
"view_structures(mol,\n", | ||
" w=400, # Make the viewer larger\n", | ||
" h=400, # Make the viewer larger\n", | ||
" labelinds=mol.ase_atoms.get_chemical_symbols(), # Add chemical symbols\n", | ||
" )\n", | ||
"labelinds = list(map(chr, range(97, 123))) * 3\n", | ||
"view_structures(mol,\n", | ||
" w=400, # Make the viewer larger\n", | ||
" h=400, # Make the viewer larger\n", | ||
" labelinds=labelinds[:len(mol.ase_atoms)], # Add arbitrary letters to each atom\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Note, this can all be done for lists of structures as well!!!\n", | ||
"labelinds = list(map(chr, range(97, 123))) * 3\n", | ||
"view_structures(mol_list,\n", | ||
" labelinds=[labelinds[:len(mol.ase_atoms)]]*len(mol_list), # Add arbitrary letters to each atom for each structure in list\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Now, we can also play with the parameters for the visualization itself.\n", | ||
"view_structures(mol,\n", | ||
" representation='stick', # Switch to stick representation\n", | ||
" stick_scale=0.5, # Make the sticks larger\n", | ||
" )\n", | ||
"view_structures(mol,\n", | ||
" representation='sphere' # Switch to sphere representation\n", | ||
" )\n", | ||
"view_structures(mol,\n", | ||
" sphere_scale=0.5, # Increase sphere scales\n", | ||
" metal_scale=1.3, # Increase metal sphere scale even more.\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Now, we can distort and relax a structure with XTB with in-built routines:\n", | ||
"distortion,_,_ = random_sampler(mol,\n", | ||
" n=1, # Produce one distortion\n", | ||
" max_rmsd=0.2 # Make sure it's not too different \n", | ||
" ) \n", | ||
"distortion = distortion[0]\n", | ||
"view_structures([mol,distortion],\n", | ||
" labels=['UFF Minima','Distorted'],\n", | ||
" columns=2)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Now, we can relax the distortion\n", | ||
"xtb_relaxed = CalcExecutor(mol,\n", | ||
" method='GFN2-xTB',\n", | ||
" relax=True,\n", | ||
" save_trajectories=True)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Now we can visulaze both the distortion and the relaxed structures\n", | ||
"view_structures([distortion,xtb_relaxed.mol],\n", | ||
" labels=['Distorted','XTB Relaxed'],\n", | ||
" columns=2\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Further, we can animate the relaxation trajectory! \n", | ||
"view_structures(xtb_relaxed.trajectory,\n", | ||
" w=400,\n", | ||
" h=400,\n", | ||
" trajectory=True # Treat as a trajectory for animation\n", | ||
" )\n", | ||
"# Note that anything that is a list of structures that architector can read (ase atoms, xyz, mol2 ...)\n", | ||
"# Can be treated as a trajectory" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Further, we can animate the relaxation trajectory! \n", | ||
"view_structures(xtb_relaxed.trajectory,\n", | ||
" w=400,\n", | ||
" h=400,\n", | ||
" interval=400, # Slow down the trajectory animation\n", | ||
" trajectory=True)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Note that this block takes around 1 minute on an M2Max Macbook Pro.\n", | ||
"calced = CalcExecutor(xtb_relaxed.mol,\n", | ||
" method='GFN2-xTB') # Re-run single point to get vibrations\n", | ||
"with arch_context_manage.make_temp_directory() as _:\n", | ||
" vib_analysis = Vibrations(calced.mol.ase_atoms) # Run vibrational analysis using ASE\n", | ||
" vib_analysis.run()\n", | ||
" data = vib_analysis.get_vibrations() # Get the vibrations\n", | ||
" hess = data.get_hessian_2d() # Get the hessian \n", | ||
"# Calculate the normal modes, force constnaces, and vibrational energies.\n", | ||
"vib_energies, modes, fconstants, _ , frequencies = vibration_analysis(calced.mol.ase_atoms,\n", | ||
" hess)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# With the vibrational modes, we can now visualize mode vibrations\n", | ||
"view_structures(calced.mol,\n", | ||
" modes=[modes[7]] # Visualize just one mode (non-zero modes start a 7)\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# We can also visualize more than one mode\n", | ||
"view_structures([calced.mol]*8,\n", | ||
" modes=modes[30:(30+8)], # Visualize First 8 modes\n", | ||
" labels=frequencies[30:(30+8)] # Add labels corresponding to the frequencies modes (cm^-1)\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Conclusions to using View Structures\n", | ||
"\n", | ||
"In this tutorial we walked through several examples highlighting view structures capabilites.\n", | ||
"\n", | ||
"Although all of these examples were performed using Architector-generated structures,\n", | ||
"\n", | ||
"All these capabilities can also be done with local files or paths pointing to structure files including xyz, mol2 ..." | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "base", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.12" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |