Making nano-batarangs (and more)
Have you ever thought about how you could create the Batman's batarang at the nanoscale? Maybe it won't fight cancer or viruses, but every scientist, like a hero, needs tools to work on their cause.
In this post, we introduce two such tools that can be used for creating nano-batarangs and other complex-shaped objects at the atomic level by selecting atoms and modifying some of their properties using mathematical expressions and scripting language.
Simple Script Extension#
The Simple Script Extension allows you to modify some properties of atoms (positions, visibility, element type, etc) in the active document according to a script provided by you. To do so, predefined variables, mathematical and logical expressions can be used in the script. Below is a description of the App's functionality.
I. Variables#
Variables are defined as in the SAMSON Node Specification Language, but only for atoms. The difference of this Extension's scripting language with the Node Specification Language is that all characters (i.e., names and symbols for elements) should be used within single quotation marks, e.g.: 'Carbon', 'Fe'. Below is a list of variables that are possible to use in the script.
Node attributes#
n.selectionFlag
(short namen.sf
) - true/1 if node is selected, false/0 if node is not selected
Atom attributes#
a.x
,a.y
, `a.z - atom's positionsa.visibilityFlag
(short namea.vf
) - true/1 if atom is visible, false/0 if atom is invisiblea.aminoAcidBackbone
(short namea.aabb
) - true/1 if atom belongs to an amino-acid backbonea.aromatic
(short namea.ar
) - true/1 if atom is aromatica.chainID
(short namea.ci
) - index of a chain to which atoms belongs to (a.ci==0 matches atoms from chain ID 0)a.formalCharge
(short namea.fc
) - atom's formal chargea.nucleicAcidBackbone
(short namea.nabb
) - true/1 if atom belongs to a nucleic-acid backbonea.occupancy
(short namea.oc
) - atom's occupancya.partialCharge
(short namea.pc
) - atom's partial chargea.residueSequenceNumber
(short namea.resi
) - index of a residue to which atom belongs to (a.resi==12 matches atoms in residue 12)a.resonance
(short namea.reso
) - true/1 if atom is resonanta.serialNumber
(short namea.sn
) - atom's serial number (a.sn>=500 matches atoms with serial number larger than 500)a.temperatureFactor
(short namea.tf
) - atom's temperature factora.water
(short namea.w
) - true/1 if atom belongs to water moleculea.element
(short namea.e
) - element name of atom (a.e=='Carbon' matches carbon atoms)a.symbol
(short namea.s
) - element symbol of atom (a.s=='H' matches hydrogen atoms)a.elementID
(short namea.ei
) - element index of atom in the periodic tablea.vdwr
- van der Waals radius of atom
It is possible to change only the next properties of atoms: n.selectionFlag, a.x, a.y, a.z, a.visibilityFlag, a.chainID, a.formalCharge, a.occupancy, a.partialCharge, a.serialNumber, a.temperatureFactor, a.elementID.
II. Capabilities: operators, functions, structures#
It is possible to use standard mathematical operators and functions, and C-like structures and statements.
- Basic operators:
+, -, *, /, %, ^
- Assignment:
:=, +=, -=, *=, /=, %=
- Equalities and inequalities:
\=, ==, <>, !=, <, <=, >, >=
- Logic operators:
and, mand, mor, nand, nor, not, or, shl, shr, xnor, xor, true, false
- Functions:
abs, avg, ceil, clamp, equal, erf, erfc, exp, expm1, floor, frac, log, log10, log1p, log2, logn, max, min, mul, ncdf, nequal, root, round, roundn, sgn, sqrt, sum, swap, trunc
- Trigonometry:
acos, acosh, asin, asinh, atan, atanh, atan2, cos, cosh, cot, csc, sec, sin, sinc, sinh, tan, tanh, hypot, rad2deg, deg2grad, deg2rad, grad2deg
- Control structures: if-then-else, ternary conditional, switch-case, return-statement
- Loop statements: while, for, repeat-until, break, continue
-
Comments:
# this is a comment // another comment /* this is also a comment */
Parsing and evaluation of expressions are done thanks to the C++ Mathematical Expression Parsing And Evaluation Library 'exprtk' by Arash Partow. See the list of possible operators, structures and other capabilities here: exprtk by Arash Partow.
Note: all variable and function names are case-insensitive.
III. Examples#
In this section, a brief introduction to the scripting language is given in several examples.
-
Set z-coordinate equal to
sin(a.x * π / 12)
for all atoms in the active document:a.z:=sin(a.x * pi / 12);
-
Shift all atoms with type 2 in y-direction by 5.25 (in the selected length units):
if (a.elementID==2) a.y+=5.25;
or the same expression using short names:
if (a.ei==2) a.y+=5.25;
-
Select all atoms with x and y coordinates greater than 0:
if (a.x > 0 and a.y > 0) n.selectionFlag:=1; else n.selectionFlag:=0;
or the same using ternary conditional statement:
( (a.x > 0) and (a.y > 0) ) ? n.sf:=1 : n.sf:=0;
-
Select all Carbon and Hydrogen atoms:
if (a.element=='Carbon' or a.symbol=='H') n.selectionFlag:=1; else n.selectionFlag:=0;
-
Show only atoms inside a sphere with radius 10 and center in (0, 0, 2) (in the selected length units):
if ((a.x^2 + a.y^2 + (a.z - 2)^2) < 100) a.visibilityFlag:=1; else a.visibilityFlag:=0;
-
Change elementID of atoms from 1 to 2 (works only with a.elementID):
if (a.elementID==1) a.elementID:=2;
-
Shift atoms with elementID equal to 1 an with x-coordinate
|x|>10
by 5 in the y-direction (in the selected length units):if (a.ei==1 and abs(a.x) > 10) a.y+=5;
-
Rotate all atoms about the x-axis by an angle
θ=π/4
:var theta:=pi/4; # create variable, the same as: theta:=deg2rad(45); var y_old:=a.y; var z_old:=a.z; a.y:=y_old * cos(theta) - z_old * sin(theta); a.z:=y_old * sin(theta) + z_old * cos(theta);
-
Switch operator:
switch { case a.x < -1 : a.y += 1.5; case a.x > 1 : a.y -= 1.5; default : a.y:=a.y; };
-
Modify z-coordinate for atoms with
|x|>10
and highlight them:if ( abs(a.x) > 10 ) { n.sf := 1; a.z := sin( a.x * pi / 12); } else { n.sf:=0; };
-
Example on nested for-loops:
for (var i:=0; i < 4; i+=1) { a.y -= 1; if (a.y < 0) continue; for (var j := 0; j < 4; j += 1) { a.z += 2; if (a.z > 10) break; }; };
-
This scripting language can be used for complex selection of atoms in the active document. For example, one can cut nano-tiles from graphene:
-
And, finally, one can create Batman's nano-batarang out of graphene. Script for creating the nano-batarang out of graphene sheet placed in the z-plane:
/* Batman's sign */ var x:=a.x / 2; // positions should be at least in nanometers var y:=a.y / 2; var iambatman:=false; if ( (abs(x)>3 and y>=0) or (abs(x)>4 and y<0)){ // wings, ellipsoidal sides if( (x/7)^2+(y/3)^2 < 1 ) iambatman:=true; } else if (abs(x)<=4 and y<0) { // central bottom part if (y >= (abs(x/2) - (3*sqrt(33)-7)*x^2/112 - 3) + sqrt(1-(abs(abs(x)-2)-1)^2) ) iambatman:=true; } else if (abs(x)<=1 and abs(x)>0.75 and y>=0) { // sides of the head if (y <= 9 - 8*abs(x) ) iambatman:=true; } else if (abs(x)<=0.75 and abs(x)>0.5 and y>=0) { // pointy ears if (y <= 3*abs(x) + 0.75 ) iambatman:=true; } else if (abs(x)<=0.5 and y>=0) { // top of the head if (y <= 2.25) iambatman:=true; } else if (abs(x)<=3 and abs(x)>1 and y>=0) { // from head to wings if (y <= 6*sqrt(10)/7 + (1.5-0.5*abs(x)) - 6*sqrt(10)/14*sqrt(4-(abs(x)-1)^2)) iambatman:=true; }; if (iambatman) { // set selectionFlag and visibilityFlag to 1 if atom is selected n.sf:=1; a.vf:=1; } else { // set selectionFlag and visibilityFlag to 0 if atom is not selected n.sf:=0; a.vf:=0; };
-
Let's now use switch instead of multiple if-statements to create a graphene batarang from Nolan's trilogy. Script for creating the nano-batarang out of graphene sheet placed in the z-plane:
/* Batarang from Nolan's trilogy */ var x:=a.x / 2; // positions should be at least in nanometers var y:=a.y / 2; var iambatman:=false; if (y >= 0 and y <= 3) { switch { // wings, top case (abs(x)>4 and abs(x)<10) : if( ((abs(x)-14)/4)^2+((y+2)/3)^2 > 4 ) { iambatman:=true; }; // from head to wings case (abs(x)>1 and abs(x)<=4) : if( ((abs(x)-1)/1.75)^2+(y-3)^2 > 3 ) { iambatman:=true; }; // sides of the head case (abs(x)<=1 and abs(x)>0.75) : if( y <= 9 - 8*abs(x) ) { iambatman:=true; }; // pointy ears case (abs(x)<=0.75 and abs(x)>0.5) : if( y <= 3*abs(x) + 0.75 ) { iambatman:=true; }; // top of the head case abs(x)<=0.5 : if( y <= 2.25 ) { iambatman:=true; }; default : iambatman:=false; }; } else if (y < 0 and y > -3.5){ switch { case (abs(x)<=6) : if( ((abs(x)-8)/4)^2+((y+3.5)/1.5)^2>4 ) { iambatman:=true; }; case (abs(x)<=10 and abs(x)>6) : if( ((abs(x)-14)/4)^2+((y+2)/3)^2>4 and y>-0.5 ) { iambatman:=true; }; default : iambatman:=false; }; } if (iambatman) { // set selectionFlag and visibilityFlag to 1 if atom is selected n.sf:=1; a.vf:=1; } else { // set selectionFlag and visibilityFlag to 0 if atom is not selected n.sf:=0; a.vf:=0; };
Atoms Selector Extension#
If you want to just select atoms using a mathematical expression, the Atoms Selector Extension might be of help. The same variables, operators and functions as in the Simple Script Extension can be used. In Atoms Selector Extension, you only need to provide an expression according to which you want atoms in the active document to be selected.
An additional keyword can be used:
all
- select all atoms in the active document.
For example, to cut a cylinder with radius 10Å out of quartz crystal (given known positions of the crystal):
((a.x-15)^2 + (a.y-15)^2) < 100
Please, let us know in the comments below what you'd like to see in SAMSON or if you have any questions.
And, to paraphrase Bruce Wayne, an App developer can be anyone! You can develop your own Apps for your needs in SAMSON thanks to the powerful SAMSON SDK.
If you have any questions or feedback, please use the SAMSON Connect Forum.