File: scripting_tutorial.tex

package info (click to toggle)
coot 1.1.18%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 220,004 kB
  • sloc: cpp: 495,934; python: 35,043; ansic: 26,143; lisp: 22,768; sh: 13,186; makefile: 2,746; awk: 441; xml: 245; csh: 14
file content (399 lines) | stat: -rw-r--r-- 13,211 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

% 10pt is the smallest font for article
\documentclass{article}

\usepackage{graphicx}
\usepackage{epsf}
\usepackage{a4wide}
\usepackage{palatino}
\usepackage{euler}
\usepackage{url}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1.2ex} 
% for simple code
\usepackage{fancyvrb}
\DefineVerbatimEnvironment{code}{Verbatim}{fontsize=\small}

% for python stuff
\usepackage{color}
\usepackage{listings}
\usepackage{textcomp}
\usepackage{setspace}
\usepackage{palatino}

\renewcommand{\lstlistlistingname}{Code Listings}
\renewcommand{\lstlistingname}{Code Listing}
\definecolor{gray}{gray}{0.5}
\definecolor{green}{rgb}{0,0.5,0}

\lstnewenvironment{python}[1][]{
\lstset{
language=python,
basicstyle=\ttfamily\small\setstretch{1},
stringstyle=\color{red},
showstringspaces=false,
alsoletter={1234567890},
otherkeywords={\ , \}, \{},
keywordstyle=\color{blue},
emph={access,and,break,class,continue,def,del,elif,else,%
except,exec,finally,for,from,global,if,import,in,is,%
lambda,not,or,pass,print,raise,return,try,while},
emphstyle=\color{black}\bfseries,
emph={[2]True, False, None, self},
emphstyle=[2]\color{green},
emph={[3]from, import, as},
emphstyle=[3]\color{blue},
upquote=true,
morecomment=[s]{"""}{"""},
commentstyle=\color{gray}\slshape,
emph={[4]1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
emphstyle=[4]\color{blue},
literate=*{:}{{\textcolor{blue}:}}{1}%
{=}{{\textcolor{blue}=}}{1}%
{-}{{\textcolor{blue}-}}{1}%
{+}{{\textcolor{blue}+}}{1}%
{*}{{\textcolor{blue}*}}{1}%
{!}{{\textcolor{blue}!}}{1}%
{(}{{\textcolor{blue}(}}{1}%
{)}{{\textcolor{blue})}}{1}%
{[}{{\textcolor{blue}[}}{1}%
{]}{{\textcolor{blue}]}}{1}%
{<}{{\textcolor{blue}<}}{1}%
{>}{{\textcolor{blue}>}}{1},%
framexleftmargin=1mm, framextopmargin=1mm, frame=shadowbox, rulesepcolor=\color{blue},#1
}}
{}
%end python stuff


% for scheme code based on python thingy (very simple)
\lstnewenvironment{guile}[1][]{
\lstset{
%language=guile,
basicstyle=\ttfamily\small\setstretch{1},
framexleftmargin=1mm, framextopmargin=1mm, frame=shadowbox, rulesepcolor=\color{green},#1
}}
{}
% end scheme


\newcommand {\atilde} {$_{\char '176}$} % tilde(~) character

\title{Coot Scripting Tutorial}

\author{Pythonic HowTos, Examples, Tutorials}

\date{\today}

\begin{document}
\maketitle
\tableofcontents
%\listoffigures


\newpage

\section{Introduction to Scripting in Coot}

\begin{code}
  c+=1
\end{code}

\begin{verbatim}
(insert literal text)
\end{verbatim}

How do we write stuff here:
green boxes: guile code
blue boxes:  python code

\subsection{Python Basics}

\subsection{Moving between Python and Scheme/Guile}
The following is (almost as is) described on the Coot WIKI (\url{http://strucbio.biologie.uni-konstanz.de/ccp4wiki/index.php/COOT#Python_to_Scheme_and_return}.
Python scripting is different to the (default) scheme scripting which is mainly described in Paul Emsley's documentation \footnote{although it's mentioned somewhere, fairly hidden; Needs reference FIXME}. In order to ``translate'' the commands you have to change them in the following way:

 GUILE scripting: (guile-command argument1 argument2 ...)

 PYTHON scripting: python\_command(argument1, argument2, ...)


\subsubsection{Simple rules for Scheme to Python translations}
Here some simple rules how to translate from Scheme to Python. To translate the other way around, i.e. Python to Scheme, just turn the rules around:
\begin{enumerate}
   \item replace all '-' with '\_' (except in equation when you need arithmetic '-' minus signs)
   \item move the brackets around the argument(s)
   \item separate multiple arguments by commas rather than spaces
   \item replace 'define' for functions with 'def' and for assignments with an '='
   \item Make sure to use indentation for the function content [Python is indentation sensitive] and a ':' after the function definition. 
\end{enumerate}
Some additional/advanced(?) rules:
\begin{enumerate}
   \item \#f $\Rightarrow$ False
   \item \#t $\Rightarrow$ True
   \item (set! variable value) $\Rightarrow$ variable=value 
\end{enumerate}

\subsubsection{A simple example}

In Scheme we may have the following script:

\begin{guile}
(define mol2-pdbFile "somePDBfile.pdb" )
(define mol2-model (read-pdb mol2-pdbFile))
(define (read-mol-again)
        (clear-and-update-model-molecule-from-file mol2-model mol2-pdbFile))
(read-mol-again)
\end{guile}

Which will translate into Python:

\begin{python}
 mol2_pdbFile = "somePDBfile.pdb"
 mol2_model = read_pdb(mol2_pdbFile)
 def read_mol_again():
     clear_and_update_model_molecule_from_file(mol2_model, mol2_pdbFile)
 read_mol_again()
\end{python}

\subsubsection{Running a Scheme/Python command from Python/Scheme}

As of Coot 0.5 (and if you have both scripting languages available) you an use the following commands to run a script or command in the other language:
\begin{code}
 (run-python-command "python_command(arg1, arg2, ...)")    [from guile/scheme]

 run_scheme_command("(scheme-command arg1 arg2 ...)")      [from python]
\end{code}


\subsection{Script execution and file structure}

\section{Internal and external functions}
\subsection{Source/internal functions}
\subsection{Provided scripting functions}

\section{HowTos and Examples}

\subsection{Add an Extension/Plugin}
Coot 'plugins' are fairly easy. Although we usually not necessarily call 
them plugins (rather scripts, extensions, ...). Here's what to do (*):

1.) write an extension script which will give you new Menu item with 
plugin entries which will execute functions, e.g. (simplified)

\begin{python}
plugin_menu = coot_menubar_menu("My Plugins")
add_simple_coot_menu_menuitem(plugin_menu, "Run plugin 1",
                                lambda func: plugin1())
\end{python}

2.) Have your plugin being able to be execute by the function 'plugin1', 
possibly merge into one file (my\_plugin.py), i.e.

\begin{python}
def plugin1():
    here some code to plugin or call plugin...

plugin_menu = .... (from above)
\end{python}

3.) Place the python script in a directory so that Coot will read it on 
startup, i.e. either:
- include in $HOME/.coot.py
- place the file into $HOME/.coot-preference
- put the file into whatever directory and set env variable 
COOT\_PYTHON\_EXTRAS\_DIR to point to that directory

or run manually with Calculate->Scripting->Run Script

4.) Done

\subsection{Make Keybindings}

\subsection{Add Toolbuttons}
\label{sec:button}
At the moment it is not trivial to add the two functions you suggest 
(*), but here are a few ways how in general to add buttons to the toolbar:

- add you favourite function to the list 'list\_of\_toolbar\_functions' in 
python/coot\_toolbuttons.py and the use the Toolbar Manager

- use 'Add a user-defined Button' and specify your favourite function

- use the function coot\_toolbar\_button in e.g. \$HOME/.coot/.py to add 
your favourite function [e.g. coot\_toolbar\_button("Sphere Refine", 
"sphere\_refine()", "reset-view.svg")  \# note: all strings, icon -last arg- is optional)

Note: you have to define your favourite function somewhere too (use Run 
Script, .coot.py, .coot-preference, or COOT\_PYTHON\_EXTRAS\_DIR ... for 
this)!!!


\subsection{User defined clicks}

\subsection{Example 1: Setting zero occupancies}
Imagine you want to have a function to set the occupancy of an atom, a whole 
residue, or a residue range to zero. Here we will use simple functions to 
program short-cuts for these and we will bind this functions to keys, buttons, clicks etc..

\subsubsection{Existing functions}
There are a few build-in functions which can manipulate occpancies. To set 
occupancies to zero in a residue range you can use:

\begin{code}
 zero_occpancy_residue_range(imol, chain_id, resno_start, resno_end)
\end{code}

To manipulate occupancies more specific and fine tuned, the following function
can be used:

\begin{code}
 set_atom_atributes(atom_attributes_settings_list)
\end{code}

where the list is\footnote{``occ'' and occupancy value may be substitutet 
with different other atom attributes, e.g. ``alt-conf''}:

\begin{code}
 atom_attribute_settings_list = [[imol, chain_id, res_no, ins_code, atom_name,
                                alt_conf, "occ", occ_value], [...], ...]
\end{code}


\subsubsection{Function to set occupancies of active residue to zero}
We can use zero\_occupancy\_residue\_range with just one residue. The 
information about the active residue we get from active\_residue().
Note: the function does not need to take arguments.

\begin{python}
def my_zero_occ_active_residue():
    active_atom = active_residue()
    # this returns False if no residue or the following list of residue
    # properties (includes atom_name of closest atom):
    # [imol, chain_id, res_no, ins_code, atom_name, alt_conf]
    if not active_atom:
        print 'no active atom'   # bail out
    else:
        # we found an active residue, get variables from list elements
        # not all needed now actually
        imol      = active_atom[0]
        chain_id  = active_atom[1]
        res_no    = active_atom[2]
        ins_code  = active_atom[3]
        atom_name = active_atom[4]
        alt_conf  = active_atom[5]
        zero_occupancy_residue_range(imol, chain_id, res_no, res_no, ins_code)

# to run just type
my_zero_occ_active_residue()
\end{python}

\subsubsection{Bind function to keyboard key}
So the function is done, but not very convienently accessible since we have
to type it in. So let's bind it to a key. For this we use the function:
\begin{code}
 add_key_binding(name, key, function)
\end{code}
So we can write simply:
\begin{python}
def my_zero_occ_active_residue():
    active_atom = active_residue()
    ... from above
add_key_binding("Set occupancy of active residue to zero", "O",
                lambda func: my_zero_occ_active_residue())
\end{python}
If you load/run this in Coot pressing the ``O'' key will set the occupancy of
the active residue to 0 (zero).

\subsubsection{Make a button for it}
For the ones rather using the mouse than keyboard short-cuts, let's make a 
button for our function to set the occupancy of the active residue to zero.
To do so we can use either method described above (\ref{sec:button}), but 
first let's use the pure scripting variant with the function:

\begin{code}
 coot_toolbar_button(button_label, callback_function[, gtk_icon]) 
\end{code}

where button\_label is the text appearing on the button and callback\_function
\footnote{Note: this is a string here!} 
the function we want to call, i.e. ``my\_zero\_occ\_active\_active\_residue()''.
The optional argument gtk\_icon specifies a gtk-stock icon to be shown on the
button. Here e.g. we could use ``gtk-remove''. Putting it together the script 
could look something like this:
\begin{python}
def my_zero_occ_active_residue():
    active_atom = active_residue()
    ... from above
coot_toolbar_button("Set occupancy of active residue to zero",
                    "my_zero_occ_active_residue()", "gtk-remove") 
\end{python}
If you run this script an extra button should appear at the main toolbar
at the top of the Coot window.
% put in coot_toolbuttons.py in preferences dir!?

For completeness we look at the way to add a button with the toolbar 
wizard as well. To get to the wizard right-mouse-click on the main toolbar.
A context menu will pop up where you select: ``Add a user-defined Button...''.
The toolbar assistent (wizard) will open.
\begin{figure}[htbp]
  \begin{center}
    \leavevmode
    \includegraphics[width=70mm]{images/toolbar_assistent1.png}
    \caption{Coot Toolbar Assistent}{Give your button a name and press 
    ``Forward''}
    \label{fig:assistent1}
  \end{center}
\end{figure}

Now give the function which should be executed

\begin{figure}[htbp]
  \begin{center}
    \leavevmode
    \includegraphics[width=70mm]{images/toolbar_assistent2.png}
    \caption{Coot Toolbar Assistent}{The function to be called, i.e. my\_zero\_occ\_active\_residue() and press ``Forward'' again}
    \label{fig:assistent2}
  \end{center}
\end{figure}

\begin{figure}[htbp]
  \begin{center}
    \leavevmode
    \includegraphics[width=70mm]{images/toolbar_assistent3.png}
    \caption{Coot Toolbar Assistent}{Select if the function sould be saved to preferences and press ``Forward'' again. The function would be saved in the filecoot\_toolbuttons.py in the directory \$HOME/.coot-preferences/. The next time you load Coot the button will appear again.}
    \label{fig:assistent3}
  \end{center}
\end{figure}

\begin{figure}[htbp]
  \begin{center}
    \leavevmode
    \includegraphics[width=70mm]{images/toolbar_assistent4.png}
    \caption{Coot Toolbar Assistent}{Select (or not) an icon for the button.}
    \label{fig:assistent3}
  \end{center}
\end{figure}

\begin{figure}[htbp]
  \begin{center}
    \leavevmode
    \includegraphics[width=70mm]{images/toolbar_assistent4b.png}
    \caption{Coot Toolbar Assistent}{A small selection of icons...}
    \label{fig:assistent3}
  \end{center}
\end{figure}

After the final ``Forward'' you will get an extra toolbutton on the main
toolbar ready to use.

\section{Excercises}



\section*{Colophon}

This document is written using XEmacs 21.5 in \LaTeX{} using AUC\TeX{}
and is distributed with the Coot source code.

\end{document}