/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2013 Frederik Heber. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /** * \file python.dox * * Created on: Nov 01, 2011 * Author: heber */ /** * \page userinterfaces-python Python module * * Via boost::python all of Molecuilder Action's are exported into a python * module such that all functionality can also be directly used in a python * script. * * This is done in \b src/Python/PythonScripting.cpp. * * There again some preprocessor magic is happening, very similar to constructs * we used for the Action's. One the one hand we need GlobalListOfActions.hpp to * have a list of all actions available. Second, in AllActionPython.hpp we define * export functions for every Action (in essence we use the COMMAND function, see * Action_impl_pre.hpp, which makes an Action usable internally as a normal * function). * * Then, at the beginning of the BOOST_PYTHON_MODULE declaration we initialize * the ActionHistory (same as in main() in builder.cpp), and on exit we * perform cleanUp() via the atexit() hook to make sure that everything * is not only removed but more importantly in the correct orders. This is * required because we use many static elements which have to be deinitialized * in the correct sequence as they depend on one another. * * \section userinterfaces-python-first-test A first test script * * A small python test script would then look like this: * \code * import pyMoleCuilder as mol * mol.WorldInput("test.xyz") * mol.SelectAtomById("0") * mol.AtomRemove() * mol.wait() * mol.getSelectedMolarMass() * mol.wait() * \endcode * which loads a file \b test.xyz into the (internal) World, selects the first * atom and removes it. * * \subsection userinterfaces-python-first-test-wait Wait may be important ... * * \note Notice \b mol.wait() at the end. This might be necessary as actions are * executed in a different thread than the python script itself. This is only * enabled when configure is called with \b enable-action-thread. * * Hence, if you require values from molecuilder you have to make sure that * all your actions have been processed by this second thread. That's what * wait() is good for. It waits until action queue thread is idle. Then you * can be sure that molecuilder has removed all atoms, performed all selections * and any value you retrieve is up-to-date. * * Note that there are two \b wait()s present in the example. As the Actions * are executed in another thread and the above commands just tell the MoleCuilder * library (the ActionQueue to be precise) to enqueue the requested action, * we have to wait (in the main thread) until the actions actually have been * executed before we continue (i.e. when we need the new state where the * atoms have been removed) and before we \b terminate! * * \section userinterfaces-python-running Running a test script * * In most cases however, python cannot find the library (except molecuilder * has been installed in some system-default folder). In this case you should * prefix your call to the python interpreter with: * \code * PYTHONPATH="/src/.libs" python * \endcode * where \a is the top build directory of molecuilder. If you have * installed molecuilder (\code make install \endcode), but the * \a (i.e. the \a prefix given at to the configure call) is non- * standard, then prepend this * \code * PYTHONPATH="/share/site-packages" python * \endcode * * \section userinterfaces-python-autostart Using python script as autostart file * * If in the current directory a file \b molecuilder.py is found, the contents * is executed as a regular python script prior to any other Action's. * * \note Each commands needs to be taken from a molecule called \a pyMoleCuilder. * Hence, use * \code * pyMoleCuilder.WorldInput("test.xyz") * pyMoleCuilder.wait() * \endcode * * \note Each command needs to be followed by brackets regardless of any present * arguments. * \code * pyMoleCuilder.SelectionAllMolecules() * pyMoleCuilder.wait() * \endcode * * \note Each argument must be given as a string as it is basically as if the * commands were given on the command line, \sa userinterfaces-commandline * \code * pyMoleCuilder.SelectAtomById("0") * pyMoleCuilder.wait() * \endcode * * \warning Again, take note of the added wait()s that ensure the all enqueued * actions also have been executed. This is especially important in scripts as * otherwise your script may deadlock. That's because ActionQueue's destructor * waits for the thread that executes the actions to end, and in another thread * we still want to access to ActionQueue whose instance is however locked as * it is about the get destroyed. * * \subsection userinterfaces-python-notes-cleanup Cleaning up or reset state ... * * Whenever you need to reset the internal state of the molecuilder, i.e. * you want to save the current file and work on something new, use * \code * mol.cleanUp() * \endcode * This frees all memory, removes all static instances on the heap, and saves * your input file (\sa WorldInputAction). * * \subsection userinterfaces-python-help Help inside the interpreter * * Note that the pyMoleCuilder module is fully documented. I.e. * \code * import pyMoleCuilder as mol * help(mol) * \endcode * gives you a complete list of present functions/Actions in the module * including their signature and a brief description (this is all * automatically generated via the proprocessor magic from the Action's * \b .def files). * * Likewise you may obtain help on each single function, e.g. * \code * import pyMoleCuilder as mol * help(mol.WorldInput) * \endcode * gives you the docu string on WorldInputAction. * * * * \date 2014-03-10 * */