CAP - Catabolite gene Activating Protein (1BER)
DNA - GATTACAGATTACAGATTACA Endonuclease PvuII bound to palindromic DNA recognition site CAGCTG (1PVI) DNA - GATTACAGATTACAGATTACA TBP - TATA box Binding Protein (1C9B)
CAP - Catabolite gene Activating Protein (1BER)
GCN4 - leucine zipper transcription factor bound to palindromic DNA recognition site ATGAC(G)TCAT (1YSA)
GCN4 - leucine zipper transcription factor bound to palindromic DNA recognition site ATGAC(G)TCAT (1YSA)
GCN4 - leucine zipper transcription factor bound to palindromic DNA recognition site ATGAC(G)TCAT (1YSA)
GCN4 - leucine zipper transcription factor bound to palindromic DNA recognition site ATGAC(G)TCAT (1YSA)
GCN4 - leucine zipper transcription factor bound to palindromic DNA recognition site ATGAC(G)TCAT (1YSA)
GCN4 - leucine zipper transcription factor bound to palindromic DNA recognition site ATGAC(G)TCAT (1YSA)
TBP - TATA box Binding Protein (1C9B)

The YANACONDA Macro Language

YASARA features an intuitive macro language that combines a syntax optimized for maximum readability and a minimum number of keystrokes with simplicity - the entire description fits on one page. YANACONDA helps to boost productivity by automating your tasks - from complex data analysis to molecular animations.


Yanaconda is Yet ANother Abridged COding 'N' Development Approach

Why yet another macro language? Why not use Python directly, as it is possible in YASARA plugins? There are two simple reasons:
  • Many users prefer not to use the graphical interface, but type the commands directly in the console to save time. In this case, every keystroke is a precious resource, and Yanaconda has been designed to minimize the number of keystrokes while maximizing the readability of the code.
So if you quickly want to color all CA and CB atoms blue, you type:
coloratom ca cb,blue

Because the command above is not a valid Python syntax, you would have to type:
ColorAtom("ca cb","blue")

In the first case, it takes 20 keystrokes, in the second case 33 (counting SHIFTs), that's 65% more. The quick way is possible because Yanaconda is not case sensitive and the command 'ColorAtom' knows its argument types and does not expect quotes around strings.
When writing a macro that will be used again, you would invest more time and choose a more readable form of the command, with the same result:
ColorAtom CA CB,Blue

  • Not everyone knows how to (or likes to) program in Python, and Yanaconda can be seen as a minimal common set of instructions that everyone knowing at least one other programming language can memorize in ten minutes. (If Yanaconda is your first 'programming language' it may take 30 minutes).


Yanaconda is a reinterpreted language

The only language the processor can understand is machine code. The low-level Assembly language is just a way to make machine code readable for humans. High-level languages like C/C++ must be translated to machine code by a compiler, or to an intermediate 'byte-code' that can be executed by an interpreter (Python,Perl).
Yanaconda is one additional level 'higher' (and slower, which is not an issue because virtually all of the time is spent in YASARA commands anyway). The source code is reinterpreted continuously and can modify itself using 'explicit evaluators' described below. This revival of 'self-modifying code' allows for surprising shortcuts that can increase readability and efficiency at the same time.


Explicit evaluators modify the source code at run time

When reading Yanaconda source code, there is one single golden rule:
Name = 'Yami'
Print 'Hi I am (Name)!'

Hi I am Yami!

And a more extreme example:
Name = 'Yami'
Function = 'Print'
Argument = 'Hi I am (Name)!'
(Function) (Argument)

Hi I am Yami!

In short, the pair of opening and closing parentheses is called an 'explicit evaluator', because it explicitly forces the evaluation of an expression at any location in the source code. The entire expression including the parentheses is replaced by the value of the expression.


When writing Yanaconda macros, use Python syntax highlighting

Much of Yanaconda's syntax has been kept compatible with Python, so that you can immediately use syntax highlighting in your favorite editor. It helps to add the file extension for Yanaconda macros '.mcr' to the editor settings. You can also use Python style comments with a double cross '#' for one line comments and triple quotes """ for multi-line comments.


The four datatypes are integer, float, weak string and strong string

Yanaconda knows four different datatypes, which are described below.


Integers remember the number of leading zeroes

Integers are numbers without a decimal point. Contrary to other programming languages, they can be defined with leading zeroes and remember them.
a = 5
b = -4003
c = 000
d = 000005

To wheat your appetite, here is an example which takes away some things explained later, but illustrates the point. Imagine you want to load 10 PDB files, named Model001 to Model010.
As a C programmer, you would type:
char filename[9];
int i;

for (i=1;i<=10;i++)
{ sprintf(filename,"Model%03d",i);
LoadPDB(filename); }

As a Python programmer, you save a lot and earn percents and a mysterious '11':
for i in range(1,11):

As a Yanaconda programmer, your life is easy:
for i=001 to 010
LoadPDB Model(i)


Floats remember their precision

Floats are numbers with a decimal point and an optional exponent. If you specify an exponent or just a dot without decimal digits, calculations will be done at maximum precision. Otherwise the result will be rounded to the number of digits after the comma.

a = 5.000 
A float with a precision of three decimal digits
b = 4e0 
A float with maximum precision (4*10^0 = 4)
c = 3. 
Just a dot without decimal digits also gives maximum precision
d = -2.5e3 
A float with maximum precision (-2.5*10^3 = -2500)
e = 7.345e-4 
Another float with maximum precision (7.345*10^-4 = 0.0007345)
f = 0.0034 
A float with a precision of four decimal digits


Weak strings are enclosed by single quotes

You already met some weak strings in the section about explicit evaluators. They are called weak because of two reasons:
  • Explicit evaluators inside the string are indeed evaluated.
  • When a weak string is explicitly evaluated, it loses the single quotes.
a = 2
b = 3
# Assign '5' to MyWeakString
MyWeakString = '(a+b)'
Print 'Result is (MyWeakString)'

Result is 5

Note that the result is 5, not '5', not (a+b) and not '(a+b)'.


Strong strings are enclosed by double quotes

Strong strings are somehow complementary to weak strings:
  • Explicit evaluators inside the string are ignored.
  • When a strong string is explicitly evaluated, it keeps the double quotes.
a = 2
b = 3
MyStrongString = "(a+b)"
Print 'Result is (MyStrongString)'

Result is "(a+b)"


The left operand defines the datatype of the result

It is easily possible to perform an operation with two operands of different datatypes. In this case, the result gets the datatype of the left operand.
a = 2
b = 1.7
# Result is a float
Print (b+a)

# Result is an integer, 3.7 rounded to 4
Print (a+b)

This simple rule permits a large number of useful applications:
  • Output formatting
pi = 3.14159265359
Print (0.00+pi)

  • Convert from floats to integers
pi = 3.14159265359
a = 0+pi
Print (a)

  • Convert to and from string
a = "2"
b = 5+a
Print (b)

a = 2
b = "5"+a
Print (b)

a = 5
b = "2"*a
Print (b)

Remember to be careful when writing more complicated mathematical expressions:


Yanaconda supports the usual operators

Most programming languages share a common set of operators. Some differences become apparent if you use multiple operators in one expression without explicitly ordering them using parentheses. Then evaluation order depends on the predefined operator priority. The operators you can use in Yanaconda are listed in the following sections. Operators of the same priority are evaluated from left to right.


The negation operator has the maximum priority 6: !, not

This operator switches true (anything except 0) to false (0) and vice versa. You can use '!' or 'not', whichever you prefer.
a = 3
b = 0

Print (!a)
Print (not b)


Operators with priority 5: *, /, //, %, <<, >>

Here are some examples for the six operators with the second highest priority. Note that the modulo operator '%' requires an integer on the left side. The '//' operator is mainly known to Python programmers, it is a division with truncation of the result's fractional part. The normal division operator '/' rounds the result to the closest integer if the requested result data type is an integer.
a = 2
b = 3.

Print (a*b)
Print (b*a)
Print (a/b)
Print (a//b)
Print (b/a)
Print (a%b)
Print (b%a)
Error - unsupported operator

The shift operators '<<' and '>>' do bitwise binary shifts to the left or right, they require an integer on the left side. A left shift corresponds to a multiplication with 2, a right shift to a division by 2. That's why they have the same priority as '*' and '/'.
a = 2
b = 3.000

Print (a<<1)
Print (a<<b)
Print (a>>1)
Print (b>>a)
Error - unsupported operator


Operators with priority 4: +, -

a = 2
b = 3.000

Print (a+b)
Print (b+a)


Operators with priority 3: >, >=, <=, <, ==, !=

All comparison operators have the third lowest priority. They return 1 if the comparison is true, 0 otherwise. Note that '!=' stands for 'is not equal to'.
a = 2
b = 3.000

Print (a>b)
Print (a<b)
Print (a==b)
Print (a!=b)


Operators with priority 2: &, |, ^

These operators do a bitwise 'and', 'or' and 'xor', there must be an integer on the left side. They are rarely if ever needed in Yanaconda.


Operators with minimum priority 1: and, or

Logical operators are used most of the time in if/else statements to combine the results of comparisons.
a = 2
b = 3

if a==1 or b==3
Print "Hello World!"

Hello World!


Indentation defines the program flow and must be a multiple of two spaces

Python introduced a very smart concept which is taken over by Yanaconda: instead of using explicit code block markers like braces '{' and '}' in C/C++ or 'begin' and 'end' in Pascal, blocks of code that belong together are identified by their indentation level. Taking away the section about conditional execution below, here is an example:
a = 2
b = 3

if a==3
Print "A equals 3!"
if b==3
Print "and B too!"
Print "but B does not"
Print "sorry, A does not equal 3"
if b==3
Print "but therefore B does!"
Print "and neither does B"

sorry, A does not equal 3
but therefore B does!

When compared to the language C, the benefits are enormous: you have to type less, do not waste space with braces, and do not spend your time searching where you forgot a brace.
However, as soon as you want to use code written by someone else, it is payback time. Python programmers know the nightmare: You receive a code-snippet by e-mail, paste it into your editor, save, run and crash. Then you spend your time hunting down little indentation problems, because the original code was written with a mixture of tabs and spaces, got additionally modified on its way through the various e-mail clients and is dead on arrival.
To keep these troubles away from Yanaconda users and promote the quick and easy exchange of macros, Yanaconda insists that indentation is done with multiples of two spaces and no tabs are used (which is the standard Python convention anyway). If you like to use the 'Tab' key, just configure your editor to replace each tab with two spaces while typing. (Virtually any source code editor with syntax highlighting can do that.) If you are very unhappy about that and would prefer a different indentation style, be assured that most of the time, you will not need any indentation at all, due to the simple nature of Yanaconda macros.


Control the program flow with if, elif and else

An example for conditional execution has been given above, the syntax is the same as in Python, 'elif' is used instead of 'else if'. Note that you cannot continue on the same line after 'if', 'elif' or 'else', you always have to start a new (indented) line.
a = 2

if a==1
Print 'A equals 1!'
elif a==2
Print 'A equals 2!'
Print 'A equals neither 1 nor 2!'

A equals 2!


There are four types of loops

Equally important as conditional execution is the ability to repeat a set of instructions for a given number of cycles or while a condition is true.


Loops can run over a range of numbers: for i = X to Y step Z

Use a for loop to cycle over a fixed range of numbers.
for i = 1 to 3
Print (i)


for i = 5 to 12 step 2
Print (i)


for i = 20.0 to 15.0 step -1.5
Print (i)


For testing purposes, you can of course also type a loop directly into the console. Just make sure to keep the indentation (the first loop iteration will execute while you type) and close the loop by typing a command without indentation:
>for i=1 to 3
> Print (i)
> Print (i*4)
>Print 'Done'


Loops can run over a list: for i in X,Y,Z,..

If you have a fixed number of elements that are either strings or non-sequential numbers, use this form of the for loop. This syntax matches Python.
for i in 5,10,3,-8
Print (i)


for text in 'Hi!','I am','Yami..'
Print (text)

I am

And you can also loop over the content of a file:
for id in file /home/yasara/pdb_id.txt
LoadPDB (id)
CountRes all

In the example above, the file pdb_id.txt contains a list of PDB IDs to loop over. In this simple text file, you can use either commas or linefeeds to separate the elements:
# Example for valid loop-file:
# Line starting with '#' are ignored.

# Using linefeeds to separate

# Using commas to separate

# By default, strings are weak strings, single quotes are not essential:
'1RIS', '1RWT'

# Double quotes are needed to specify strong strings:

# Integers and floats are also allowed:
5.7, -1e60


Loops can run while an expression is true: while X and do .. while X

In addition to the Python syntax, Yanaconda supports the C-like do .. while X style. In the latter case, the loop is run at least once, even if the expression at the end is false.
i = 3
while i<50
Print (i)
i = i*2


i = 60
Print (i)
i = i*2
while i<50



Stop a loop with 'break'

Like C and Python, Yanaconda supports the 'break' statement to stop a loop. In addition, it is possible to specify the number of nested loops to stop right after the 'break'.
i = 0
while 1
Print (i)
if i==5
i = i+1


for i=1 to 3
for j=10 to 15
Print (i)-(j)
if j==12
break 2



Loop ahead with 'continue'

The 'continue' statement has also been borrowed from C and Python. Again, you can specify the number of the loop to continue with.
for i=1 to 3
for j=10 to 15
if j==12
continue 2
Print (i)-(j)



Lists are emulated with explicit evaluators

Having a list of something (strings, numbers) can be very handy.
for i = 1 to 5
MyList(i) = i*10
for i = 5 to 1
Print (MyList(i))


Note that lists are not a special datatype but 'faked' using explicit evaluators. The first for loop creates five variables named 'MyList1' to 'MyList5', and the second for loop simply prints them out in reversed order.
If you assign more than one value to a variable, it is assumed to be a list, and the 'fake' variables Name1,Name2…NameN are created automatically. You can document the fact that MyList is a list by appending two parentheses.
MyList() = 4,7,8,9,5
for i in MyList
Print (i)
for i = 1 to 5
Print 'Element (i): (MyList(i))'
Print 'Accessing list elements:'
MyList(3) = MyList(3)+1
Print (MyList(3))
MyList3 = MyList3+1
Print (MyList3)

Element 1: 4
Element 2: 7
Element 3: 8
Element 4: 9
Element 5: 5
Accessing list elements:

To delete a list, use:

This expression will set MyList1 to 0 and delete all other variables with the same root name 'MyList'.
The same concept holds for multidimensional lists, but care must be taken that the list indices do not interfere, best by separating them with an underscore '_':
for i=1 to 12
for j=1 to 12

Why is the first matrix wrong? Simply because the matrix elements 1,12 and 11,2 (like several others) map to the same variable name: wrongmatrix112. The underscore makes sure that the indices stay separated: rightmatrix1_12 and rightmatrix11_2 are indeed different names.
If you know the number of columns and rows in advance, you can use leading zeroes to avoid the underscore:
for i=01 to 12
for j=01 to 12

In the above case, rightmatrix0112 and rightmatrix1102 correctly map to different variable names.


The 'count' function determines the length of lists

As lists are just variables with the same root name and a sequential number at the end, the length of a list can be determined by counting the number of names that match a certain pattern. This is done by the 'count' function:
MyList() = 4,8,5,2
for i = 1 to count MyList
Print 'Element (i): (MyList(i))'

Element 1: 4
Element 2: 8
Element 3: 5
Element 4: 2

If no variable name matches, 'count' returns 0 to indicate that the list is empty / does not exist.


The 'min', 'max', 'sum', 'mean', 'stddev' functions return the smallest, largest, sum, mean and standard deviation of all list elements

These five functions scan all variable names that match the given root name and return the smallest, largest, summed up and average value, respectively. The datatype of the result is either an integer or float, depending on the list elements. The standard deviation is calculated using the formula:
StdDev^2 = Sum((ElementX-Mean)^2) / Elements

Example for a simple list:
MyList() = 1,4,-5,10,8,2
Print (count MyList)
Print (min MyList)
Print (max MyList)
Print (sum MyList)
Print (mean MyList)
Print (stddev MyList)



Yanaconda macros can access predefined variables

Some variables are predefined to make life easier, they are just normal variables and can be overwritten.

View 1 if the stage of your YASARA is at least View, always true
Model 1 if the stage of your YASARA is at least Model (true for Model, Dynamics, Structure), 0 otherwise
Dynamics 1 if the stage of your YASARA is at least Dynamics (true for Dynamics, Structure), 0 otherwise
Structure 1 if the stage of your YASARA is at least Structure (true for Structure only), 0 otherwise
Twinset 1 if you have the Twinset installed
Movie 1 if you are running YASARA Movie
Windows 1 if the operating system is Windows
Linux 1 if the operating system is Linux
MacroDir Directory where the current macro resides
MacroTarget Target set for this macro with the MacroTarget command
Atoms Number of atoms in the soup, see also Count
Objects Number of objects in the soup , see also Count
FirstObj Number of first defined object, 0 if no object defined
LastObj Number of last defined object, 0 if no object defined
EnergyUnit Current EnergyUnit, either 'kcal/mol' or 'kJ/mol'
SpeedMax The current speed of the fastest atom in the simulation in m/s
Pi The value of Pi, 3.14159265359
Pid The ID of the current process (helpful if you create temporary files)
LeftButton 1 if the left mouse button is currently pressed
MiddleButton 1 if the middle mouse button is currently pressed
RightButton 1 if the right mouse button is currently pressed
FirstName Your first name, type Print 'Hi (FirstName)!' to greet yourself.
LastName Your last name
ScrSizeX The width of the YASARA window in pixels
ScrSizeY The height of the YASARA window in pixels
PixToA Conversion factor from pixels to Ås
EyeDis Distance between the eye and the viewplane in Ås


Yanaconda macros can include each other

Sometimes a certain macro is needed at more than one place. Instead of copying macros manually between files, you can use the 'include' statement to let a macro include other macros:
# Solve an NMR structure
# First fold it from the stretched out conformation
include nmr_fold
# Then refine it in vacuo
include nmr_refinevac
# And then in water
include nmr_refinewat

  • The 'include' statement does not have to be placed in the first column (YASARA will instead automatically indent the included file as well).
  • YASARA includes the other macros BEFORE running the macro. As a consequence, the line numbers reported in case of errors refer to the complete macro, with all the others included.


Calls to built in functions can be placed anywhere within an expression

Yanaconda supports a number of built-in functions, mainly for doing math. These functions can appear anywhere in an expression. If the function argument is itself an expression, you must enclose it in parentheses. Remember to leave a space between the function name and the opening parenthesis.
for i = 0 to 180 step 60
j = sqrt i
k = cos (i)
Print 'Sqrt of (i) = (j), Cos of (i) = (k)'

Sqrt of 0 = 0.00000000000000e+00, Cos of 0 = 1.00000000000000e+00
Sqrt of 60 = 7.74596669241483e+00, Cos of 60 = 5.00000000000015e-01
Sqrt of 120 = 1.09544511501033e+01, Cos of 120 = -4.99999999999969e-01
Sqrt of 180 = 1.34164078649987e+01, Cos of 180 = -1.00000000000000e+00

Unlike C and Python, trigonometric functions expect their arguments in normal degrees.
The following functions are available:

abs X Absolute value of X
acos X Arc cosine of X, returned in degrees
asin X Arc sine of X, returned in degrees
atan X Arc tangent of X, returned in degrees
cos X Cosine of X, X in degrees
count X The number of occurances of variables with root name X and different terminal numbers
cube X Volume of a cube with length X = X*X*X
curt X Cubic root
exp X e (the base of natural logarithms) raised to the power X
log X Natural logarithm of X
log10 X Base-10 logarithm of X
max X The maximum value in list X (all variables with root name X)
mean X The mean value of list X (all variables with root name X)
min X The minimum value in list X (all variables with root name X)
onein X A random element in list X (all variables with root name X)
ord X The ASCII code of string X, summed up if string contains more than one character
rnd X A random number in the range [0..X[
round X X rounded to the closest integer
sign X The sign of X, either 1, 0 or -1.
sin X Sine of X, X in degrees
sqr X Area of a square with length X = X*X
sqrt X Square root
stddev X The standard deviation of list X (all variables with root name X)
sum X The sum of all values in list X (all variables with root name X)
tan X Tangent of X, X in degrees
trunc X The integer part of X, rounded towards zero.


Calls to YASARA commands must appear one per line

The most important part of any macro are the YASARA commands. Yanaconda is merely used to guide the control flow and call YASARA commands with the right parameters. Almost every example in this section used YASARA's 'Print' command to print results.
YASARA commands know which arguments to expect. E.g. the DelAtom command expects a selection. To save your time, selections are not enclosed by any quotes.
DelAtom CA

This will obviously delete all CA (=Calpha) atoms. Now let's put the atom name in a variable:
Name = 'CA'
DelAtom (Name)

Note that you must use an explicit evaluator so that (Name) is replaced with CA, otherwise YASARA would delete all atoms named 'Name'. If you look at previous examples, you can see that all Print commands that printed variables used explicit evaluators to insert the content of the variable. Otherwise just its name would have been printed.
You can of course also use variables for more complicated selections, e.g. for salt-bridges:
selection = 'Lys Atom NZ with distance < 4 from Asp Glu'
ShowRes (selection)
ColorRes (selection),blue

This brings us to the final golden rule for Yanaconda programmers:
Some YASARA commands return values that can be assigned to variables. This example stores the X/Y/Z coordinates of atom 500 in three variables x,y and z:
x,y,z = PosAtom 500

If a command returns more results than variables present, the additional return values will be lost. In this case, the Y and Z coordinates are discarded:
x = PosAtom 500

It is also possible to put the return values in a list by appending two parentheses to the variable name:
pos() = PosAtom 500
Print X=(pos(1)) Y=(pos(2)) Z=(pos(3))

This feature is especially useful to store selections returned by the List command, e.g. the command ColorAtom CA,Red can be expressed as:
selection() = ListAtom CA
for atom in selection
ColorAtom (atom),Red

If you want to know if a command returns something, look at the examples given for the command.