 °  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: 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:
 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 lowlevel Assembly language is just a way to make machine code readable for humans. Highlevel languages like C/C++ must be translated to machine code by a compiler,
or to an intermediate 'bytecode' 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 'selfmodifying 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:
EVERYTHING ENCLOSED IN PARENTHESES ( ) IS EVALUATED AND REPLACED BY THE RESULT
Example:
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 multiline 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. Examples:
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): LoadPDB("Model%03d"%i)
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.
Examples:

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.345e4
 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.
Example:
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.
Example:
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. Example:
a = 2 b = 1.7 # Result is a float Print (b+a) 3.7 # Result is an integer, 3.7 rounded to 4 Print (a+b) 4
This simple rule permits a large number of useful applications:
pi = 3.14159265359 Print (0.00+pi) 3.14
 Convert from floats to integers
pi = 3.14159265359 a = 0+pi Print (a) 3
 Convert to and from string
a = "2" b = 5+a Print (b) 7 a = 2 b = "5"+a Print (b) "52" a = 5 b = "2"*a Print (b) "22222"
Remember to be careful when writing more complicated mathematical expressions:
 DEFINE FLOATS WITH AN EXPONENT TO GAIN MAXIMUM PRECISION
 PUT THE INTEGERS ON THE RIGHT SIDE TO PREVENT THEM FROM CONVERTING FLOATS
°  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) 0 Print (not b) 1
°  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) 6 Print (b*a) 6.0000000000e0 Print (a/b) 1 Print (a//b) 0 Print (b/a) 1.5000000000e0 Print (a%b) 2 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) 4 Print (a<<b) 16 Print (a>>1) 1 Print (b>>a) Error  unsupported operator
°  Operators with priority 4: +,  
a = 2 b = 3.000 Print (a+b) 5 Print (b+a) 5.000
°  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) 0 Print (a<b) 1 Print (a==b) 0 Print (a!=b) 1
°  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!" else Print "but B does not" else Print "sorry, A does not equal 3" if b==3 Print "but therefore B does!" else 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 codesnippet by email,
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 email 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!' else 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) 1 2 3 for i = 5 to 12 step 2 Print (i) 5 7 9 11 for i = 20.0 to 15.0 step 1.5 Print (i) 20.0 18.5 17.0 15.5
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) 1 > Print (i*4) 4 >Print 'Done' 2 8 3 12 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 nonsequential numbers,
use this form of the for loop. This syntax matches Python.
for i in 5,10,3,8 Print (i) 5 10 3 8 for text in 'Hi!','I am','Yami..' Print (text) Hi! I am Yami..
And you can also loop over the content of a file:
for id in file /home/yasara/pdb_id.txt Clear 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 loopfile: # Line starting with '#' are ignored. # Using linefeeds to separate 1CRN 5TIM # Using commas to separate 1SOL, 1STY,1THV # By default, strings are weak strings, single quotes are not essential: '1RIS', '1RWT' # Double quotes are needed to specify strong strings: "1VII","1YAS" # Integers and floats are also allowed: 1,2,3 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 Clike 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 3 6 12 24 48 i = 60 do Print (i) i = i*2 while i<50 60
°  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 break i = i+1 0 1 2 3 4 5
for i=1 to 3 for j=10 to 15 Print (i)(j) if j==12 break 2 110 111 112
°  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) 110 111 210 211 310 311

°  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)) 50 40 30 20 10
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) 4 7 8 9 5 Element 1: 4 Element 2: 7 Element 3: 8 Element 4: 9 Element 5: 5 Accessing list elements: 9 10
To delete a list, use:
MyList()=0
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 wrongmatrix(i)(j)=i*j rightmatrix(i)_(j)=i*j
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 rightmatrix(i)(j)=i*j
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((ElementXMean)^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) 6 5 10 20 3.33333333333333e+00

°  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 Angstroms 
EyeDis  Distance between the eye and the viewplane in Angstroms 

°  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 builtin 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.00000000000015e01 Sqrt of 120 = 1.09544511501033e+01, Cos of 120 = 4.99999999999969e01 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  Base10 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. 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 saltbridges:
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:
ALWAYS USE EXPLICIT EVALUATORS AROUND YANACONDA EXPRESSIONS THAT APPEAR AS ARGUMENTS TO YASARA COMMANDS.
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: 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:
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.
