<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2980252964491090926</id><updated>2011-09-09T03:08:38.578-07:00</updated><category term='boost'/><category term='Qt'/><category term='SIP'/><category term='cheminformatics javascript closure JSON Ajax HTML5'/><category term='smiles stereochemistry trigonal-bipyramidal octahedral'/><category term='python'/><category term='symmetry permutation automorphism stereochemistry'/><title type='text'>OB, Avogadro and Molecular Modelling</title><subtitle type='html'>openbabel and avogadro</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-7049663222311509986</id><published>2010-10-11T19:09:00.001-07:00</published><updated>2010-10-12T12:24:40.235-07:00</updated><title type='text'>CMake, CTest and CDash: Creating portable c++ software</title><content type='html'>&lt;a href="http://www.cmake.org"&gt;CMake&lt;/a&gt; is a powerful build system for C++ applications (and other languages) used by many software projects including KDE. The main difference between CMake and other build systems is that it generates native unix make files, Microsoft Visual C++ solutions or XCode projects. Before we adopted cmake, we had to maintain separate build files for windows and unix/mac platforms. A developer using a specific platform would not update the other platform's build files which often resulted in compile errors when another developer checked out the new code. While fixing these errors is usually a trivial task, it's still an inconvenience. Using CMake solves this problem without adding any additional dependencies. CMake is small and binaries for a large number of platforms are provided.&lt;br /&gt;&lt;br /&gt;CTest is part of CMake and can be used to test software. It doesn't provide any code but functions as a way to run the tests. For example, in OpenBabel we have a header where we define some functions we can use to write unit tests: OB_ASSERT, OB_REQUIRE and OB_COMPARE. Implementations of these functions are simple but any unit testing framework (code library, headers) can be used. Our functions print "FAIL" to the standard output and we use this as regular expression to allow CTest to determine if a test has failed. The advantage of using CTest is that we can now use the tests to improve the quality of our software. This becomes possible because CMake/CTest can submit the results to CDash.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/TLS13mIjE7I/AAAAAAAAAIo/txmdjAntRcE/s1600/cdash.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 200px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/TLS13mIjE7I/AAAAAAAAAIo/txmdjAntRcE/s320/cdash.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5527242609424274354" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The OpenBabel dashboard is available &lt;a href="http://my.cdash.org/index.php?project=Open+Babel&amp;display=project"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;CDash is a web application containing the status of building and testing your software. KitWare provides CDash hosting but you still need to set up build "sites". These sites are just computers that run a CTest script as scheduled task or cronjob. For example, several developers and users from OpenBabel run these scripts every night and these results are submitted to CDash for all developers to see. We have multiple configurations to cover the most frequently used platforms and compilers (win, linux, mac, gcc, cygwin, MSVC, 32/64 bit, ...) but this depends on the platforms you want to support for your project. CTest synchronizes the Nightly builds so all sites will use the same revision which makes it easy to spot differences between platforms.&lt;br /&gt;&lt;br /&gt;We also use Continuous builds which means that every time a developer checks in changes, an (incremental) build will be done, the tests will run and the results are submitted to CDash. This is complementary to the Nightly builds. For example, if for a Nightly run, a unit test failed on all platforms and there were 20 commits. The continuous results will identify which commit caused the test to start failing.&lt;br /&gt;&lt;br /&gt;CDash can also be used for other information beyond compile warnings/errors and test results. For example, it is easy to include code code coverage and memory leak detection. For code coverage, CTest has support for GNU GCov and a commercial tool Bullseye. For OpenBabel, we split the coverage in two to differentiate between the core library and plugins. This is possible by using subprojects but it currently takes two builds and I'm still experimenting with the script. I'm told support for this will be improved in future versions but if the number of subprojects is small, the multiuiple build approach works. It runs cmake and defines some variables that enable code coverage for the library or formats (i.e. -fprofile-ars -ftest-coverage for gcov). The building directory is emptied between builds to ensure the gcov files are removed before analysing the new coverage results. The script can be found &lt;a href="http://pastebin.org/156637"&gt;here&lt;/a&gt; and the changes to the OpenBabel CMakeLists.txt files &lt;a href="http://pastebin.org/156643"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Another supported feature is memory checking to find memory leaks. In linux, valgrind is supported. This takes some time to run if the number of tests is large but running this Nightly is enough. It is also possible to submit additional files.&lt;br /&gt;&lt;br /&gt;Acknowledgements: I'd like to thank &lt;a href="http://blog.cryos.net/"&gt;Marcus Hanwell&lt;/a&gt; and &lt;a href="http://kitware.com/"&gt;Kitware&lt;/a&gt; for providing CDash hosting and other contributions to OpenBabel and Avogadro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-7049663222311509986?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/7049663222311509986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=7049663222311509986' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/7049663222311509986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/7049663222311509986'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2010/10/cmake-ctest-and-cdash-creating-portable.html' title='CMake, CTest and CDash: Creating portable c++ software'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_vRYlXAlReRw/TLS13mIjE7I/AAAAAAAAAIo/txmdjAntRcE/s72-c/cdash.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-3485692031611569287</id><published>2010-09-16T17:37:00.000-07:00</published><updated>2010-09-16T20:15:26.579-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='smiles stereochemistry trigonal-bipyramidal octahedral'/><title type='text'>The SMILES stereochemistry enigma</title><content type='html'>Almost every cheminformatics system implementing smiles limits the support for stereochemistry to the tetrahedral and double bond cases. Some (e.g. OpenBabel, Jmol, ...) implement the square planar SP tags which only has 3 possible values. However, the daylight smiles page has very limited documentation when it comes to trigonal-bipyramidal and octahedral stereochemistry. All strictly needed information is there though and this blog post will give an overview of how to obtain the meaning of the TB3-TB20 and OH3-OH30 tags.&lt;br /&gt;&lt;br /&gt;Since the trigonal-bipyramidal case is slightly easier it will be discussed first. As can be seen in the image below, not all ligands are equivalent. There are two axial ligands (S and F) and three equatorial ligands (Cl, Br, I).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/TJLZVvqlXjI/AAAAAAAAAIg/ApdyAkH8Ack/s1600/TB.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 117px; height: 150px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/TJLZVvqlXjI/AAAAAAAAAIg/ApdyAkH8Ack/s320/TB.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5517711461077835314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The TB1 tag is documented on the daylight website meaning viewing from the first ligand atom to the last, the three remaining ligands are ordered counter clockwise (i.e. @). A valid smiles for the depicted molecule would be F[X@TB1](I)(Br)(Cl)S. TB2 means viewing along the same axis, the three remaining are clockwise (i.e. @@). With this information it is possible to write any molecule by hand since you can reorder the atoms as needed. However, when writing out a canonical smiles, the order of the atoms is determined by the canonicalization algorithm and there are 5! = 120 possible ways to order 5 ligands. Since the ligands are not equivalent, there must be a way to encode the axis ligand positions using the tags. This hypothesis is supported by the fact that there are 10 ways to position the axis atoms (a-e, a-d, a-c, a-b, b-e, b-d, b-c, c-e, c-d, d-e), 10 * 2 (@|@@) = 20 tags and each tag has 3! = 6 permutations associated with it resulting in 120 permutations total.&lt;br /&gt;&lt;br /&gt;To find the order of these axis, the more subtle information from the daylight smiles specification can be used. The first clue is that TH1 and TH2 are two cases of a generic chiral specification method. The other clues are that tags are actually "chiral permutation designators" and "it's table driven". Now all that is left to do is enumerate all permutations lexicographically and assign the designators when a new axis is found. The first column is the permutation number, the second is the permutation itself, the 3th column is are the axis positions, the 4th is the winding and finally the designator. (note: TB1/TB2 are designated first, skipping permutation 2)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;1: 01234 0-4 @ TB1&lt;br /&gt;2: 01243 0-3 @ TB3&lt;br /&gt;3: 01324 0-4 @@ TB2&lt;br /&gt;4: 01342 0-3 @@ TB4&lt;br /&gt;5: 01423 0-2 @ TB5&lt;br /&gt;6: 01432 0-2 @@ TB6&lt;br /&gt;7: 02134 0-4 @@ TB2&lt;br /&gt;8: 02143 0-3 @@ TB4&lt;br /&gt;9: 02314 0-4 @ TB1&lt;br /&gt;10: 02341 0-3 @ TB3&lt;br /&gt;11: 02413 0-2 @@ TB6&lt;br /&gt;12: 02431 0-2 @ TB5&lt;br /&gt;13: 03124 0-4 @ TB1&lt;br /&gt;14: 03142 0-3 @ TB3&lt;br /&gt;15: 03214 0-4 @@ TB2&lt;br /&gt;16: 03241 0-3 @@ TB4&lt;br /&gt;17: 03412 0-2 @ TB5&lt;br /&gt;18: 03421 0-2 @@ TB6&lt;br /&gt;19: 04123 0-1 @ TB7&lt;br /&gt;20: 04132 0-1 @@ TB8&lt;br /&gt;21: 04213 0-1 @@ TB8&lt;br /&gt;22: 04231 0-1 @ TB7&lt;br /&gt;23: 04312 0-1 @ TB7&lt;br /&gt;24: 04321 0-1 @@ TB8&lt;br /&gt;25: 10234 1-4 @ TB9&lt;br /&gt;26: 10243 1-3 @ TB10&lt;br /&gt;27: 10324 1-4 @@ TB11&lt;br /&gt;28: 10342 1-3 @@ TB12&lt;br /&gt;29: 10423 1-2 @ TB13&lt;br /&gt;30: 10432 1-2 @@ TB14&lt;br /&gt;31: 12034 2-4 @ TB15&lt;br /&gt;32: 12043 2-3 @ TB16&lt;br /&gt;33: 12304 3-4 @ TB17&lt;br /&gt;34: 12340 3-4 @@ TB18 (40 @ -&gt; @@)&lt;br /&gt;35: 12403 2-3 @@ TB19 (40 @ -&gt; @@&lt;br /&gt;36: 12430 2-4 @@ TB20 (40 @ -&gt; @@)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This enumeration can be done by hand or using a simple program. However, the information is easier to read when rearranged:&lt;br /&gt;&lt;br /&gt;TB1/TB2: axis 0-4, @/@@&lt;br /&gt;TB3/TB4: axis 0-3, @/@@&lt;br /&gt;TB5/TB6: axis 0-2, @/@@&lt;br /&gt;TB7/TB8: axis 0-1, @/@@&lt;br /&gt;TB9/TB11: axis 1-4, @/@@&lt;br /&gt;TB10/TB12: axis 1-3, @/@@&lt;br /&gt;TB13/TB14: axis 1-2, @/@@&lt;br /&gt;TB15/TB20: axis 2-4, @/@@&lt;br /&gt;TB16/TB19: axis 2-3, @/@@&lt;br /&gt;TB17/TB18: axis 3-4, @/@@&lt;br /&gt;&lt;br /&gt;The octahedral designators can be obtained in the same way. Although there seem to be three axes to choose from, the requirement to list the remaining 4 ligands clockwise or counter clockwise restricts the number of axes to 1. The additional ligand results in 15 possible axis combinations giving rise to 30 designators. A c++ example program generating these designators can be found &lt;a href="http://pastebin.org/911466"&gt;here&lt;/a&gt;. For OH1-OH30 the following designators are obtained:&lt;br /&gt;&lt;br /&gt;OH1/OH2: axis 0-5, @/@@&lt;br /&gt;OH3/OH4: axis 0-4, @/@@&lt;br /&gt;OH5/OH6: axis 0-3, @/@@&lt;br /&gt;OH7/OH8: axis 0-2, @/@@&lt;br /&gt;OH9/OH10: axis 0-1, @/@@&lt;br /&gt;OH11/OH13: axis 1-5, @/@@&lt;br /&gt;OH12/OH14: axis 1-4, @/@@&lt;br /&gt;OH15/OH16: axis 1-3, @/@@&lt;br /&gt;OH17/OH18: axis 1-2, @/@@&lt;br /&gt;OH19/OH21: axis 2-5, @/@@&lt;br /&gt;OH20/OH22: axis 2-4, @/@@&lt;br /&gt;OH23/OH24: axis 2-3, @/@@&lt;br /&gt;OH25/OH30: axis 3-5, @/@@&lt;br /&gt;OH26/OH29: axis 3-4, @/@@&lt;br /&gt;OH27/OH28: axis 4-5, @/@@&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-3485692031611569287?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/3485692031611569287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=3485692031611569287' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3485692031611569287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3485692031611569287'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2010/09/smiles-stereochemistry-enigma.html' title='The SMILES stereochemistry enigma'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_vRYlXAlReRw/TJLZVvqlXjI/AAAAAAAAAIg/ApdyAkH8Ack/s72-c/TB.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-3503705673615524106</id><published>2010-06-12T18:09:00.001-07:00</published><updated>2010-06-14T19:49:20.098-07:00</updated><title type='text'>Cheminformatics &amp; Javascript: Part 2 (Ring perception)</title><content type='html'>In the second post of the javascript series ring perception will be used as an example to illustrate some of the difficulties to overcome when developing a javascript cheminformatics library. Readers only interested in ring perception can skip the first part. The ring perception section contains some useful (algorithm) tips for speeding up ring perception not only in javascript.&lt;br /&gt;&lt;br /&gt;The topics discussed in this post result from working on jchemhub. It's still a very young project soon to be renamed to &lt;a href="http://github.com/kemia/kemia"&gt;kemia&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Some javascript benchmarks&lt;/h2&gt;&lt;br /&gt;Like I said in the previous post, firefox &amp;amp; chrome javascript performance is impressive Unfortunately, at the other end of the spectrum there is internet explorer. The way simple things like iterating over an array are done can make a huge difference. To illustrate, here are 4 code samples for iterating over the elements of an array. The preferred way is highlighted in green.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;b&gt;// example 1: check arr.length each iteration&lt;/b&gt;&lt;br /&gt;for (var i = 0; i &amp;lt; arr.length; i++) {&lt;br /&gt;  var tmp = arr[i] + arr[i];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 136, 0);"&gt;&lt;br /&gt;&lt;b&gt;// example 2: store arr.length in a variable&lt;/b&gt;&lt;br /&gt;for (var i = 0, li = arr.length; i &amp;lt; li; i++) {&lt;br /&gt;  var tmp = arr[i] + arr[i];&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;// example 3: for ... in ...&lt;/b&gt;&lt;br /&gt;for (var i in arr) {&lt;br /&gt;  var tmp = arr[i] + arr[i];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;b&gt;// example 4: forEach&lt;/b&gt;&lt;br /&gt;function doStuff(element, index, arr) {&lt;br /&gt;  var tmp = arr[index] + arr[index];&lt;br /&gt;}&lt;br /&gt;goog.array.forEach(doStuff);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/TBQylQmal5I/AAAAAAAAAHY/oksMIZs5Jus/s1600/iterate_array_ie.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 254px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/TBQylQmal5I/AAAAAAAAAHY/oksMIZs5Jus/s320/iterate_array_ie.png" alt="" id="BLOGGER_PHOTO_ID_5482062262109378450" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/TBQyuNPhNGI/AAAAAAAAAHg/pa7d94Y3ALk/s1600/iterate_array.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 259px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/TBQyuNPhNGI/AAAAAAAAAHg/pa7d94Y3ALk/s320/iterate_array.png" alt="" id="BLOGGER_PHOTO_ID_5482062415826859106" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It should be obvious that both &lt;b&gt;for ... in ...&lt;/b&gt; and &lt;b&gt;forEach&lt;/b&gt; should be avoided at all cost. To non-javascript developers, the &lt;b&gt;for ... in ..&lt;/b&gt; syntax might be surprising. It doesn't give you the elements but the keys to the elements. As a result, you still need the &lt;b&gt;var element = elements[i];&lt;/b&gt; line and there is not much benefit over a classic c-style for loop. No optimization is done when running javascript and accessing an &lt;b&gt;arr.length&lt;/b&gt; property for each iteration, will be slower than storing the property in a local variable.&lt;br /&gt;&lt;br /&gt;The second benchmark shows the overhead of a function call for accessing an object property.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var obj = { x: [], getX: function(index) {return this.x[index]; } };&lt;br /&gt;for (var i = 0; i &amp;lt; 10000; i++) {&lt;br /&gt;  obj.x.push({});&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: rgb(0, 136, 0);"&gt;&lt;br /&gt;&lt;b&gt;// example 1: direct access&lt;/b&gt;&lt;br /&gt;for (var i = 0; i &amp;lt; 10000; i++) {&lt;br /&gt;  obj.x[i];&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;// example 2: wrapper function&lt;/b&gt;&lt;br /&gt;for (var i = 0; i &amp;lt; 10000; i++) {&lt;br /&gt; obj.getX(i);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/TBQ6W_GUwqI/AAAAAAAAAHo/N_wzGpCLFv4/s1600/function_call.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 243px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/TBQ6W_GUwqI/AAAAAAAAAHo/N_wzGpCLFv4/s320/function_call.png" alt="" id="BLOGGER_PHOTO_ID_5482070812986229410" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A final benchmark shows that common knowledge from using other languages may not always apply. When creating an array of known size, using push() to expand the array is the fastest method in chrome. This is not true for internet explorer and the best compromise are the first two examples.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 136, 0);"&gt;&lt;br /&gt;&lt;b&gt;// example 1: Use goog.array.repeat.&lt;/b&gt;&lt;br /&gt;var arr1 = goog.array.repeat(2, 100000);&lt;br /&gt;&lt;br /&gt;&lt;b&gt;// example 2: Use access by index&lt;/b&gt;&lt;br /&gt;var arr2 = [];&lt;br /&gt;for (var i = 0; i &amp;lt; 100000; i++) {&lt;br /&gt;  arr2[i] = 2;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;// example 3: Allocate using access by index.&lt;/b&gt;&lt;br /&gt;var arr3 = [];&lt;br /&gt;arr3[99999] = 2;&lt;br /&gt;for (var i = 0; i &amp;lt; 100000; i++) {&lt;br /&gt;  arr3[i] = 2;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;b&gt;// example 4: Use push&lt;/b&gt;&lt;br /&gt;var arr4 = [];&lt;br /&gt;for (var i = 0; i &amp;lt; 100000; i++) {&lt;br /&gt;  arr4.push(2);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/TBQ8zBcD3RI/AAAAAAAAAHw/puBUtVoj2so/s1600/create_array_ie.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 254px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/TBQ8zBcD3RI/AAAAAAAAAHw/puBUtVoj2so/s320/create_array_ie.png" alt="" id="BLOGGER_PHOTO_ID_5482073493673860370" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/TBQ9LDC6btI/AAAAAAAAAH4/hq29sKRkk-s/s1600/create_array.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 246px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/TBQ9LDC6btI/AAAAAAAAAH4/hq29sKRkk-s/s320/create_array.png" alt="" id="BLOGGER_PHOTO_ID_5482073906422116050" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;More of these benchmarks will appear in the future on &lt;a href="http://timvdm.github.com/bench.html"&gt;this page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Ring perception&lt;/h2&gt;&lt;br /&gt;There haven't been any posts on this blog about ring perception before. The aim of ring perception is simple, it finds the rings in a molecule. Ring perception is also required in various other fields like electrical engineering. While it may be easy to get the concept, actually implementing it (efficiently) is not straightforward. There are various algorithms to compute the rings in a graph and the results are not the same. The algorithms can be classified by their output ring sets. In this post, exhaustive ring search and the Smallest Set of Smallest Rings (SSSR) will be discussed. An interesting approach combining both algorithms is also presented.&lt;br /&gt;&lt;br /&gt;Exhaustive ring search generates a large ring set containing all possible rings. This includes many combinations of rings. The Hanser algorithm is the fastest exhaustive algorithm. However, finding all rings in a reasonable large molecule will be slow. Fortunately, a depth or maximum ring size can be specified. For many structures, rings up to size 6 are often enough and the algorithm is really fast in these cases. Increasing the maximum ring size quickly results in unacceptable performance though. Using other programming languages such as c++ or java, it might be possible to increase the maximal ring size to make it usable for depiction. The implementation in jchemhub is ported from the &lt;a href="http://metamolecular.com/mx"&gt;MX java cheminformatics library&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The Smallest Set of Smallest Rings (SSSR) is a popular kind of ring set. The number of sssr rings in a molecule (single connected fragment) is given by Cauchy's formulla:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;m - n + 1       m: number of bonds&lt;br /&gt;               n: number of atoms&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If the molecule contains more disconnected fragments, 1 can be replaced with the fragment count. Knowing the number of rings in the sssr set in advance can be used for various optimizations. The simplest optimization is to conclude there are no rings if the formula is equal to 0. SSSR rings have their disadvantages though. For example, SSSR rings are not canonical, the found rings will depend on the atom order of the input molecule. This would be a good topic for an additional blog post but for now the SSSR will be good enough.&lt;br /&gt;&lt;br /&gt;There are several algorithms to compute the SSSR such as Berger's and Figueras' algorithm. The algorithm in jchemhub implements a &lt;a href="http://www.pnas.org/content/106/41/17355.full"&gt;recent algorithm that makes use of path-included distance matrices&lt;/a&gt;. The algorithm is based on the Floyd-Warhsall algorithm for computing the distance matrix. The element i,j in a distance matrix is the length of the shortest path (i.e. number of bonds) connecting atoms with index i and j. Two additional matrices are created at the same time containing the shortest path and the shortest path+1 between atoms i and j. From these path-included matrices, the ring candidates can be computed. The method has an O(n^3) runtime where n is the number of atoms. This isn't bad for finding the SSSR but using it on large molecules can be time consuming.&lt;br /&gt;&lt;br /&gt;The ideal algorithm would be fast when there are only small rings but it should also detect large rings. To solve this problem, both algorithms can be combined. First the Hanser algorithm detects all rings up to size 6. From this ring set, an attempt is made to construct the SSSR using a XOR function to test if a ring is already in the SSSR. If the full SSSR is found (i.e. the number of rings in the set after selection is equal to the calculated number of rings), the molecule doesn't contain any rings larger than 6. However, if the full SSSR set is not found the real SSSR algorithm is used to find all the rings of the SSSR including the larger rings.&lt;br /&gt;&lt;br /&gt;To evaluate the combined ring search approach, the use case is important. When doing substructure search, the average time is the most important. If an individual molecule takes some more time to process, thi is not a problem as long as the whole process is fast. The graph below shows the average time for each algorithm. A rapid decrease in performance for the Hanser algorithm can be seen. Also, the combined algorithm is 3.4 times faster than the SSSR algorithm. These tests are done in &lt;a href="http://nodejs.org/"&gt;nodejs&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/TBRfrpCp58I/AAAAAAAAAIA/tggajNFmx6g/s1600/average.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 222px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/TBRfrpCp58I/AAAAAAAAAIA/tggajNFmx6g/s320/average.png" alt="" id="BLOGGER_PHOTO_ID_5482111849772738498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A second graph shows the worst case for each algorithm. This is relevant for use cases like on-the-fly depiction. Here it doesn't matter if all molecules take 50ms more as long as there are no cases that seem to take forever and make the browser unresponsive. The SSSR algorithm can take up to 6 seconds limiting it's use. The same applies for the Hanser algorithm with larger maximal ring sizes.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/TBaFBgYSeRI/AAAAAAAAAII/5nV5z8attbM/s1600/worstcase_23000.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 221px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/TBaFBgYSeRI/AAAAAAAAAII/5nV5z8attbM/s320/worstcase_23000.png" alt="" id="BLOGGER_PHOTO_ID_5482715857288329490" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the previous graphs, a simple optimization is used. All terminal atoms are progressively removed until there are no more terminal atoms. This reduces the molecule's size and therefore improves the performance of the ring perception (regardless of the algorithm). This worked great on firefox and chrome but wasn't enough for internet explorer 7. Internet explorer is still widely used and it should be supported. Combining the algorithms and the simple atom removal brought IE7's time for perceiving rings in a 534 atom molecule down to around 10 seconds. To get it down to the current 500ms another trick was needed.&lt;br /&gt;&lt;br /&gt;Ring membership for atoms can be computed using an O(n) algorithm. A breath-first iteration is done and visited atoms and bonds are tracked together with the atom depth. When a exploring the bonds from an atom to continue iterating, there will be cases where the bond isn't visited yet but the atom it connects to is. In these cases, the bond is a ring-closure. When a ring-closure is found a backtrack can be performed to set isInCycle properties for the atoms in the ring until the paths converge. Using this atom ring membership information, the molecule can be divided in merged ring systems (i.e. rings with at least one atom in common are part of the same ring system). Running ring perception on these smaller molecules makes a huge difference when using an O(n^3) algorithm. This together with some IE7 specific performance benchmarks allowed the algorithm to be efficient in IE7 too. The worst case for the 23000 molecules in nodejs is now only 49ms. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/TBbmEVJ791I/AAAAAAAAAIQ/185r4hYK-i8/s1600/worstcase_23000_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 223px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/TBbmEVJ791I/AAAAAAAAAIQ/185r4hYK-i8/s320/worstcase_23000_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5482822558442846034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In conclusion, it is possible to make cheminformatics software using javascript, even for Internet Explorer. Doing so requires a clever combination of algorithms and programming though. The next bottleneck is rendering, VML in IE is slow...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-3503705673615524106?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/3503705673615524106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=3503705673615524106' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3503705673615524106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3503705673615524106'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2010/06/cheminformatics-javascript-part-2-ring.html' title='Cheminformatics &amp; Javascript: Part 2 (Ring perception)'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vRYlXAlReRw/TBQylQmal5I/AAAAAAAAAHY/oksMIZs5Jus/s72-c/iterate_array_ie.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-393062792617698959</id><published>2010-05-21T05:34:00.000-07:00</published><updated>2010-05-21T15:40:38.201-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cheminformatics javascript closure JSON Ajax HTML5'/><title type='text'>Cheminformatics &amp; Javascript: Part 1</title><content type='html'>&lt;span style="font-family:arial;"&gt;Richard Apodaca already made several posts on this topic on &lt;a href="http://depth-first.com/articles/2010/05/17/cheminformatics-in-javascript-jchemhub"&gt;his blog&lt;/a&gt;. After experimenting with javascript for the past few weeks, I agree with him that javascript could have a role in future web applications. Exciting things happening in browser land. For example, javascript performance has increased significantly and HTML5 features like &lt;a href="http://en.wikipedia.org/wiki/Canvas_element"&gt;canvas&lt;/a&gt; are becoming more mainstream (i.e. Firefox, Chrome, ...). Even &lt;a href="http://www.khronos.org/webgl/"&gt;webGL&lt;/a&gt; is already supported by bleeding edge firefox/chrome.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;This is the first post in a new series about cheminformatics using javascript. Since javascript is not java, I thought it would be a good idea to introduce some features of the javascript language. More interesting cheminformatics examples will follow.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Object literals &amp;amp; JSON&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;In javascript, you can create objects using object literals. This is also called &lt;a href="http://www.json.org/"&gt;JavaScript Object Notation (JSON)&lt;/a&gt;. To create an empty object:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var a = {};&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;We can also create an object with properties and functions:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var atom = { element: "C", x: 4, y: 5, bonds: [3, 4], getSomething: function(){return 42;} };&lt;br /&gt;&lt;br /&gt;atom.element // = "C"&lt;br /&gt;atom.bonds // = [3, 4] &lt;- this is an Array atom.getSomething(); // = 42 &lt;/pre&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;Javascript is a very dynamic language, so you can always add new properties and functions later.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;atom.atomicNumber = 6;&lt;br /&gt;atom.getAtomicNumber = function() {&lt;br /&gt; return this.atomicNumber;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-family:arial;"&gt;The object literal or &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; format is also used to encode data when doing &lt;a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29"&gt;AJAX&lt;/a&gt;. While the X in &lt;a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29"&gt;AJAX&lt;/a&gt; stands for XML, the latter can be replaced by &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt;. Many web API's return data in &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; (e.g. Google APIs).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Namespaces&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;There are no namespaces in javascript. However, to avoid name conflicts with other libraries, it is always a good idea to hide private parts of your code. This can be accomplished by using an anonymous function and directly calling it:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(function() {&lt;br /&gt;&lt;br /&gt; var hiddenVariable = 0;&lt;br /&gt;&lt;br /&gt; function hiddenFunction() {&lt;br /&gt;   return 34;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; window.visibleFunction = function() {&lt;br /&gt;   return hiddenFunction();&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt;})();&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Cross-domain AJAX&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;A normal &lt;a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29"&gt;AJAX&lt;/a&gt; request (i.e. same-domain) is done using the XMLHtmlRequest object. For security reasons, the browser doesn't allow the XMLHtmlRequest object to do cross-domain requests. To get around this, a technique called &lt;a href="http://en.wikipedia.org/wiki/JSON#JSONP"&gt;JSONP&lt;/a&gt; is used:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function myCallback(data) {&lt;br /&gt; ...do something with data...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function xAjax(url) {&lt;br /&gt; var head = document.getElementsByTagName("head")[0];&lt;br /&gt; var script = document.createElement("script");&lt;br /&gt; script.type = "text/javascript";&lt;br /&gt; script.src = url;&lt;br /&gt; head.appendChild(script);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;xAjax("http://otherdomain.com/app1?smiles=CCC&amp;amp;callback=myCallback");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The xAjax function creates a new script element inside the head element. The src property is set to the url to load. The callback parameter in the url is used by the server to generate valid javascript:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;myCallback({ ...JSON data... });&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;As a result, the browser will execute the myCallback function when the new script element is loaded and we can do something with the data.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;font-size:100%;"  &gt;Closure&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29#Uses_of_closures"&gt;Closure&lt;/a&gt; is a very cool javascript feature. In the example below, the private1 function has access to the outer function variables, even after returning from the outer function. This allows private1 to access the foo property. If self.foo is replaced by this.foo, the property is not found since this refers to the private1 function. This usage of closure (i.e self = this) is often found in javascript code.&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function outer() {&lt;br /&gt; this.foo = 0;&lt;br /&gt; var self = this;&lt;br /&gt;&lt;br /&gt; function private1() {&lt;br /&gt;   return self.foo;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; this.public1 = function() {&lt;br /&gt;   return private1();&lt;br /&gt; };&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Javascript libraries&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;As for most languages, there are many libraries for javascript. Some of the better ones for general purposes are &lt;/span&gt;&lt;a style="font-family: arial;" href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt;&lt;span style="font-family:arial;"&gt;, &lt;/span&gt;&lt;a style="font-family: arial;" href="http://jquery.com/"&gt;jQuery&lt;/a&gt;&lt;span style="font-family:arial;"&gt; and &lt;/span&gt;&lt;a style="font-family: arial;" href="http://www.dojotoolkit.org/"&gt;Dojo&lt;/a&gt;&lt;span style="font-family:arial;"&gt;. Google also released their &lt;a href="http://code.google.com/closure/"&gt;javascript closure tools&lt;/a&gt;. The tools include a compiler to &lt;/span&gt;&lt;a style="font-family: arial;" href="http://en.wikipedia.org/wiki/Minification_%28programming%29"&gt;minify&lt;/a&gt; &lt;span style="font-family:arial;"&gt;javascript&lt;/span&gt; &lt;span style="font-family:arial;"&gt;code&lt;/span&gt;.  &lt;a style="font-family: arial;" href="http://github.com/chemhack/jchemhub"&gt;JChemHub&lt;/a&gt;&lt;span style="font-family:arial;"&gt;, a new javascript cheminformatics library uses it extensively. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-393062792617698959?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/393062792617698959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=393062792617698959' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/393062792617698959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/393062792617698959'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2010/05/cheminformatics-javascript-part-1.html' title='Cheminformatics &amp; Javascript: Part 1'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-7523581939228510002</id><published>2010-03-21T08:22:00.000-07:00</published><updated>2010-03-22T05:47:14.318-07:00</updated><title type='text'>Detecting stereogenic units: An alternative method</title><content type='html'>In case you already saw part of this post: I accidentally pressed publish before finishing. Sorry... &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The detection of stereogenic units in a molecule isn't always a trivial task. This is illustrated by two previous blog posts (&lt;a href="http://timvdm.blogspot.com/2009/09/as-promised-here-are-some-molecules.html"&gt;post 1&lt;/a&gt; &lt;a href="http://timvdm.blogspot.com/2009/09/more-para-stereocenters-permutation.html"&gt;post 2&lt;/a&gt;) where the stereogenic units do not have 4 topological different ligands. The posts also list the set of rules that enable the detection of these stereogenic units as can be found in the referenced paper[1]. While there are only 3 rules, the amount of code needed to implement them is big. The rest of this blog post will describe an alternative method to detect these stereogenic units from a paper by the same authors[2]. &lt;br /&gt;&lt;br /&gt;A potential stereogenic center is any atom with at least 3 heavy atom neighbors. For some atoms (e.g. nitrogen), the barrier of inversion is low and these atoms are not stereogenic centers. The definition for a tetrahedral stereogenic atom is now:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;A potential stereogenic centre &lt;span style="font-weight:bold;"&gt;really is&lt;/span&gt; a &lt;span style="font-weight:bold;"&gt;stereogenic centre&lt;/span&gt; if there exists no automorphic permutation causing an inversion of the configuration of &lt;span style="font-weight:bold;"&gt;only&lt;/span&gt; the potential stereogenic centre under consideration.&lt;br /&gt;&lt;br /&gt;If there exists at least one automorphic permutation causing the inversion of the configuration of only the stereogenic centre under consideration, then the potential stereogenic centre &lt;span style="font-weight:bold;"&gt;can be&lt;/span&gt; a stereogenic centre if the number of topologically equivalent neighbours (ligands) of potential stereogenic centre is less than or equal to the number of configurations of these ligands.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;At first sight, the new definition is much simpler compared to the 3 rules. However, when it comes to implementing this, there is a catch. The second part of the definition requires the number of configurations of a topologically equivalent ligand to be computed. This could eventually leads to code comparable to the previous rules. Nevertheless, the definition is brief and easy to remember. The need for the automorphic permutations limits it's manual use though.&lt;br /&gt;&lt;br /&gt;To illustrate how the definition works, a few examples will be covered next. The first example is the most simple case where there are 4 different ligands.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/S6aq8hoL84I/AAAAAAAAAGY/5OL1JtDlsKs/s1600-h/simple.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 112px; height: 80px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/S6aq8hoL84I/AAAAAAAAAGY/5OL1JtDlsKs/s320/simple.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451232355774362498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For these cases, there exists no automorphims that only invert the center. In fact, for molecules like these there is only the identity permutation. The next example illustrates where an automorphism exists that inverts the potential stereogenic center only.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/S6arGHoCc-I/AAAAAAAAAGg/SS-5XQaQ72U/s1600-h/exists.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 70px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/S6arGHoCc-I/AAAAAAAAAGg/SS-5XQaQ72U/s320/exists.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451232520593109986" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In both cases, there will exist an automorphism that will invert the center (i.e. exchange the two equivalent methyl groups). Therefore, both potential stereo centers are not stereo centers.&lt;br /&gt;&lt;br /&gt;A more interesting example is 1,4-dihydroxy-cyclohexane. In this case, there are 4 automorphisms but none of them invert only center 1 or 4. 2 of the 4 permutations invert both center 1 and 4. Atoms 1 and 4 are therefore stereogenic centers.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S6arPSdbvoI/AAAAAAAAAGo/5EZ5Gdps4Lw/s1600-h/dihydro.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 127px; height: 211px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S6arPSdbvoI/AAAAAAAAAGo/5EZ5Gdps4Lw/s320/dihydro.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451232678120242818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The second part of the definition correctly identifies the central stereo centers in the following molecules. In all 3 cases, the number of configurations for the ligand is greater than the number of equivalent ligands.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/S6arZMl3vUI/AAAAAAAAAGw/hnFRIhe9JRA/s1600-h/central.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 262px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/S6arZMl3vUI/AAAAAAAAAGw/hnFRIhe9JRA/s320/central.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451232848343711042" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The number of equivalent ligands are 3 for the two structures on top and 2 for the bottom structure. For the top two, the number of configurations is 4 (&gt;= 3). Likewise, the number of configurations for the bottom structure is 2 (&gt;=2). The central stereogenic center is successfully found in the 3 cases.&lt;br /&gt;&lt;br /&gt;Finally, two examples where the number of configurations in the equivalent ligands is lower than the number of equivalent ligands. In both cases, there are 3 equivalent ligands and only 2 configurations for the ligand (2&lt;=3). The central atoms are therefore not stereogenic since at least one configuration will be duplicated.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S6arhzKR6JI/AAAAAAAAAG4/BKtv-zv7eu0/s1600-h/nostereo.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 203px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S6arhzKR6JI/AAAAAAAAAG4/BKtv-zv7eu0/s320/nostereo.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451232996135921810" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From the last two figures, it should be clear that counting the number of configurations in a ligand is not the same as the number of stereo centers times two. The paper doesn't really go into the details on how to do this. However, another concept introduced by the paper might be useful here: a set of interdependent stereo centers. These sets can be found be inspecting the automorphisms. A set can contain one or more stereo centers and these sets are the independent stereogenic units in a molecule. Some examples showing the sets of interdependent stereo centers in different colors should make this easier to understand.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/S6armsKnnYI/AAAAAAAAAHA/pWvq6-z8DP8/s1600-h/interdependent.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 148px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/S6armsKnnYI/AAAAAAAAAHA/pWvq6-z8DP8/s320/interdependent.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451233080157642114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/S6arqLGCLUI/AAAAAAAAAHI/U0S2Vo5wxKQ/s1600-h/interdependent2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 145px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/S6arqLGCLUI/AAAAAAAAAHI/U0S2Vo5wxKQ/s320/interdependent2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451233139999518018" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For all examples given above, the number of configurations is the same as the number of interdependent sets of stereo centers in the ligand times 2. Unfortunately, this is not true in all cases. Below is an examples where this would not work.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S6dklBKHgwI/AAAAAAAAAHQ/xPsj73Tddqg/s1600-h/config.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 294px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S6dklBKHgwI/AAAAAAAAAHQ/xPsj73Tddqg/s320/config.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5451436461084082946" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Until I find a good way to count the number of configurations, the new definition is not preferable over the old rules. I'll keep looking though and will post my findings. Suggestions are always welcome of course.&lt;br /&gt;&lt;br /&gt;[1] M. Razinger, K. Balasubramanian, M. Perdih, M. E. Munk,&lt;br /&gt;Stereoisomere Generation in Computer-Enhanced Structure Elucidation,&lt;br /&gt;J. Chem. Inf. Comput. Si. 1993, 33, 812-825&lt;br /&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.83.126&amp;rep=rep1&amp;type=pdf"&gt;pdf&lt;/a&gt;&lt;br /&gt;[2] M. Perdih, M. Razinger, Stereochemistry and Sequence Rules: A Proposal for Modification of Cahn-Ingold-Prelog System, Tetrahedron: Asymmetry, 1994, Vol. 5, No. 5, 835-861 &lt;a href="http://dx.doi.org/10.1016/S0957-4166(00)86237-0"&gt;http://dx.doi.org/10.1016/S0957-4166(00)86237-0&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-7523581939228510002?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/7523581939228510002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=7523581939228510002' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/7523581939228510002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/7523581939228510002'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2010/03/detecting-stereogenic-units-alternative.html' title='Detecting stereogenic units: An alternative method'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vRYlXAlReRw/S6aq8hoL84I/AAAAAAAAAGY/5OL1JtDlsKs/s72-c/simple.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-1801521834677877309</id><published>2010-03-09T17:14:00.001-08:00</published><updated>2010-03-10T06:08:34.199-08:00</updated><title type='text'></title><content type='html'>It has been 6 months since my &lt;a href="http://timvdm.blogspot.com/2009/09/automorphism-group-bliss.html"&gt;last post&lt;/a&gt; on stereochemistry. At the end of the post, the automorphisms for inositol were listed. These will now be used to enumerate all possible stereoisomers for a structure. Most of this post is only a summary, for details the &lt;a href="http://www.mcs.csueastbay.edu/~kbalasub/reprints/282.pdf"&gt;Razinger paper&lt;/a&gt; can be consulted.&lt;br /&gt;&lt;br /&gt;The first use of the automorphisms is to construct stereoindex vectors. These vectors contain 1 for all true stereocenters. Para-stereocenters are assigned -1 if the permutation interchanges equivalent atoms and 1 otherwise (see &lt;a href="http://timvdm.blogspot.com/2009/09/more-para-stereocenters-permutation.html"&gt;this post&lt;/a&gt; for examples of para-stereocenters).   The automorphisms, or permutations in general can be represented as a matrix which can be multiplied by the stereoindex vectors. The resulting matrices are called signed permutation matrices and they are the key to revealing identical stereoisomers. For performance reasons only the stereogenic atoms are considered when constructing the signed permutation matrices. For example, inositol containing 6 tetrahedral stereocenters will have 6x6 signed permutation matrices.&lt;br /&gt;&lt;br /&gt;Before the enumeration can begin, another matrix called the stereoparity matrix is needed. This matrix has n columns where n is equal to the number of stereocenters. There are 2^n rows in the matrix, one for each possible combination of the values 1 and -1. This is best illustrated with this example for 3 stereocenters.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/S5b-CQVeZ6I/AAAAAAAAAEw/TN5JGRpTTLw/s1600-h/paritymatrix.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 163px; height: 238px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/S5b-CQVeZ6I/AAAAAAAAAEw/TN5JGRpTTLw/s320/paritymatrix.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5446820114049427362" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The enumeration now begins by selecting row 1 from the stereoparitymatrix. This row is multiplied by each of the signed permutation matrices. The resulting row vectors are compared with the rows from the stereoparity matrix. Matching rows are redundancies of the same stereoisomer and are not considered in further steps. The identified stereoisomer can still become an enantiomer or diastereomer. This is determined by inverting row 1 and multiplying this with the signed permutation matrices. If any of the resulting vectors match a non redundant row, an enantiomers pair is found. If all resulting vectors match already redundant rows, a diastereomer is found. The same steps are repeated until all rows are assigned to a stereoisomer.  &lt;br /&gt;&lt;br /&gt;Determining the number and kind of stereoisomers alone isn't of much use though. A much more useful feature would be to generate each stereoisomer. For each stereoisomer, any of the rows assigned to it can be used. These rows can now be considered as parities for the stereogenic units in the molecule. The input molecule's data structures can be modified to match the parities in the row. Using inositol as example once more, the 9 possible stereoisomer smiles are:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/S5cSha3JHrI/AAAAAAAAAFA/Q8ZAoS5B60o/s1600-h/inositol.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 87px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/S5cSha3JHrI/AAAAAAAAAFA/Q8ZAoS5B60o/s320/inositol.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5446842639683493554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The smiles are in fact canonical smiles. The information obtained by enumerating stereoisomers can also be used for this purpose. However, this time we are only interested in the stereoisomer specified by the input molecule. The redundant set of parities associated with it can be considered to be canonical candidates. Since the stereoparity matrix contains 2^n rows, every possible candidate for a given stereoisomer is guaranteed to be found. Canonical smiles for molecules like the ones below now becomes possible. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/S5cPkccXFmI/AAAAAAAAAE4/nJR4lpezsUI/s1600-h/example.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 225px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/S5cPkccXFmI/AAAAAAAAAE4/nJR4lpezsUI/s320/example.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5446839393112757858" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The current code can be found &lt;a href="http://github.com/timvdm/openbabel-razinger"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;PS: Sorry for the delay...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-1801521834677877309?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/1801521834677877309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=1801521834677877309' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/1801521834677877309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/1801521834677877309'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2010/03/it-has-been-6-months-since-my-last-post.html' title=''/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_vRYlXAlReRw/S5b-CQVeZ6I/AAAAAAAAAEw/TN5JGRpTTLw/s72-c/paritymatrix.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-1724924438590069134</id><published>2010-03-03T13:01:00.000-08:00</published><updated>2010-03-03T15:08:29.217-08:00</updated><title type='text'>Avogadro's packmol plugin</title><content type='html'>When running molecular dynamics  (MD) simulations, one often needs to create an initial input structure. It is important that none of the atoms are too close to prevent the coordinates from "blowing up". Many MD programs provide their own utilities (e.g. &lt;a href="http://www.gromacs.org/Documentation/Gromacs_Utilities/genbox"&gt;gromacs' genbox&lt;/a&gt;) to create basic systems. For example, a protein with solvent (water) and counter ions. The counter ions are important to make the system charge neutral for algorithms like &lt;a href="http://en.wikipedia.org/wiki/Ewald_summation"&gt;Ewald summation&lt;/a&gt; or the faster &lt;a href="http://en.wikipedia.org/wiki/Ewald_summation#Particle_mesh_Ewald_.28PME.29_method"&gt;PME&lt;/a&gt;. While these utilities are often enough, creating complex input files is not always easy.&lt;br /&gt;&lt;br /&gt;Luckily, there is a program dedicated to this task: &lt;a href="http://www.ime.unicamp.br/~martinez/packmol/"&gt;Packmol&lt;/a&gt;. It uses simple text input files to define a system. The syntax is very easy to learn but writing the files by hand is a tedious task. Many of the required calculations can be automated and I started writing the Avogadro packmol plugin to do just that. The plugin should allow novice users to create complex systems and should also allow experienced users to make small adjustments (e.g. adding keywords, parameters).&lt;br /&gt;&lt;br /&gt;The work flow of the plugin is as follows:&lt;br /&gt;- Configure parameters in a wizard:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/S47TEhrvVxI/AAAAAAAAADI/hg5J0xHPQq4/s1600-h/wizard_solute.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/S47TEhrvVxI/AAAAAAAAADI/hg5J0xHPQq4/s320/wizard_solute.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444521074252273426" /&gt;&lt;/a&gt;&lt;br /&gt;The plugin allows you to browse for all required files. This allows all files to be copied to a temporarily location to make sure all files are found. The screen shot shows the wizard for the most basic systems containing solvent and optionally solute.&lt;br /&gt;&lt;br /&gt;- Clicking "Generate input file" shows the generated input file&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S47TtgCWjSI/AAAAAAAAADQ/C22oooOGqcU/s1600-h/text_mode.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S47TtgCWjSI/AAAAAAAAADQ/C22oooOGqcU/s320/text_mode.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444521778184883490" /&gt;&lt;/a&gt;&lt;br /&gt;If a new structure is added in the Text Mode tab, the plugin will ask for the file's location when the user clicks run. The syntax highlighting is there to prevent typing errors, it really helps :-)&lt;br /&gt;&lt;br /&gt;- Clicking "Run Packmol" starts the program and shows the progress in the Output tab:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/S47UaTM41qI/AAAAAAAAADY/pS-Dkyv6dJU/s1600-h/output.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/S47UaTM41qI/AAAAAAAAADY/pS-Dkyv6dJU/s320/output.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444522547833525922" /&gt;&lt;/a&gt;&lt;br /&gt;Once the program finishes, the resulting file is opened in Avogadro.&lt;br /&gt;&lt;br /&gt;The result from the input file seen in the screen shot looks like:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/S47X7gshJiI/AAAAAAAAADg/vfBn2vuS4fI/s1600-h/water.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 190px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/S47X7gshJiI/AAAAAAAAADg/vfBn2vuS4fI/s320/water.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444526416926418466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One of the most important calculations required is the number of molecules required to fill a given volume. Given the density, molecular weight and volume, the number of molecules can easily be calculated using Avogadro's number. (This is the same calculation the &lt;a href="http://www.ime.unicamp.br/~martinez/packmol/nmols.html"&gt;volume guesser&lt;/a&gt; on packmol's site uses AFAIK)&lt;br /&gt;&lt;br /&gt;The next step towards more complex systems would be to add solute and counter ions. I'm not completely sure how to subtract the volume taken by solute from the solvents volume. Computing the solute's volume might be an option. Ideas are welcome. :-)&lt;br /&gt;&lt;br /&gt;Lipid bilayers are the next kind of system that can be created with packmol. This requires some more knowledge of the packmol syntax but it is still human readable. Before continuing, it might be good to review the bilayer &lt;a href="http://www.ime.unicamp.br/~martinez/packmol/examples/index.html"&gt;input example from the packmol website&lt;/a&gt;. It has comments explaining how to the constraints are used to define the system. The wizard dialog currently looks like:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S47baQSnjyI/AAAAAAAAADo/6AxRpeeQADM/s1600-h/bilayer_input.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S47baQSnjyI/AAAAAAAAADo/6AxRpeeQADM/s320/bilayer_input.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444530243633647394" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Currently only 1 "polar solvent" type and 1 "lipid" type are allowed but the idea is that this could allow for mixtures of lipids and so on. &lt;br /&gt;&lt;br /&gt;To orient the lipids in the correct way, constraints are needed on specific atoms. This is currently a limitation since a user still has to specify the atom indexes for the polar head and lipophilic tail. In the screen shot below, the indexes have already been filled in.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/S47c2olFodI/AAAAAAAAADw/4xA_iW7Vpa0/s1600-h/bilayer_input2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/S47c2olFodI/AAAAAAAAADw/4xA_iW7Vpa0/s320/bilayer_input2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444531830701531602" /&gt;&lt;/a&gt;&lt;br /&gt;The required indexes can easily be determined by opening the lipid structure file and enabling the label display type in Avogadro though.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/S47eDVbl3yI/AAAAAAAAAD4/s7coQKdWXv0/s1600-h/lipid.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 181px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/S47eDVbl3yI/AAAAAAAAAD4/s7coQKdWXv0/s320/lipid.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444533148411354914" /&gt;&lt;/a&gt;&lt;br /&gt;The result from the input above (rendered with POV-Ray):&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/S47g-RicneI/AAAAAAAAAEA/p_OMme_Zu5o/s1600-h/result.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/S47g-RicneI/AAAAAAAAAEA/p_OMme_Zu5o/s320/result.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444536360001904098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The next logical step would be to insert a membrane protein between the lipids. This requires the orientation and position of the protein in the membrane to be known. From the protein database files, there is no easy way to determine this. In many cases, the orientations of proteins in membrane (OPM) database provides exactly this. From their website:&lt;br /&gt;&lt;blockquote&gt;The original PDB coordinates are transformed so that the calculated membrane normal coincides with the Z axis, and the origin of coordinates corresponds to the middle of membrane.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This is how the plugin generates the lipid bilayer which allows the protein to be inserted with only a few lines added:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S47pDdwHk4I/AAAAAAAAAEI/85yXnldjRaQ/s1600-h/bilayer_input3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 258px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S47pDdwHk4I/AAAAAAAAAEI/85yXnldjRaQ/s320/bilayer_input3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444545245272839042" /&gt;&lt;/a&gt;&lt;br /&gt;Again, the volume of the protein isn't considered yet. Using slightly lower numbers should work for now. After waiting a while the result should look like:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S47q9HWwMlI/AAAAAAAAAEY/HqbUqSOUiqY/s1600-h/result1_.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 181px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S47q9HWwMlI/AAAAAAAAAEY/HqbUqSOUiqY/s320/result1_.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444547335204909650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/S47rUcxNFpI/AAAAAAAAAEg/eLkTGa7ld-U/s1600-h/result2_.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 181px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/S47rUcxNFpI/AAAAAAAAAEg/eLkTGa7ld-U/s320/result2_.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444547736089990802" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/S47rbOrscbI/AAAAAAAAAEo/GsTocpi15lQ/s1600-h/result3_.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 181px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/S47rbOrscbI/AAAAAAAAAEo/GsTocpi15lQ/s320/result3_.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5444547852567867826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The source code can be found &lt;a href="http://github.com/timvdm/Avogadro-Packmol-Extension"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;(The files from the OPM database contain dummy atoms marking where the membrane should be. Make sure to remove these if you try to replicate this)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-1724924438590069134?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/1724924438590069134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=1724924438590069134' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/1724924438590069134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/1724924438590069134'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2010/03/avogadros-packmol-plugin.html' title='Avogadro&apos;s packmol plugin'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vRYlXAlReRw/S47TEhrvVxI/AAAAAAAAADI/hg5J0xHPQq4/s72-c/wizard_solute.png' height='72' width='72'/><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-3552513943200088952</id><published>2009-09-29T10:15:00.000-07:00</published><updated>2009-09-29T11:12:12.549-07:00</updated><title type='text'>The automorphism group &amp; bliss</title><content type='html'>In the &lt;a href="http://timvdm.blogspot.com/2009/09/more-para-stereocenters-permutation.html"&gt;previous post&lt;/a&gt;, an algorithm for computing the automorphism group was given. Although it drastically reduced the number of permutations to be checked, it was still much to slow for use in cheminformatics systems. A real world example is inositol where there are 2 orbits of 6 atoms. This example was also used for a &lt;a href="http://depth-first.com/articles/2009/09/16/stereochemistry-puzzler-how-many-stereoisomers-for-these-69-structures"&gt;stereochemistry-puzzler on Depth-First&lt;/a&gt; (&lt;a href="http://depth-first.com/articles/2009/09/17/stereochemistry-puzzler-answers"&gt;answer&lt;/a&gt;). Since it is a good example (i.e. it contains "large" orbits) to test the performance and correctness (there are only 9 stereoisomers) of an implementation, I'll be using it for the following posts too.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/SsJF3GYxkhI/AAAAAAAAAC8/0_FcEhPIeHo/s1600-h/inositol.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 174px; height: 220px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/SsJF3GYxkhI/AAAAAAAAAC8/0_FcEhPIeHo/s320/inositol.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5386944917198180882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;While 6! * 6! = 518400 is already way faster better than 12! = 479001600, computing half a million matrix equations still takes a considerable amount of time.  The actual time (seconds to minutes) depends on implementation details but the method is generally inefficient.&lt;br /&gt;&lt;br /&gt;A faster set of algorithms to solve this problem are known as backtracking algorithms. Some well known examples include &lt;a href="http://amalfi.dis.unina.it/graph/db/vflib-2.0/doc/vflib.html"&gt;VFLib&lt;/a&gt; (for isomorphisms in general) and &lt;a href="http://cs.anu.edu.au/~bdm/nauty/"&gt;nauty&lt;/a&gt; (automorphisms). Another, relatively new algorithm called &lt;a href="http://www.tcs.hut.fi/Software/bliss/index.html"&gt;bliss&lt;/a&gt; (paper available from their site, MIT license) came to my attention. It is a very small library which computes a set of generators of the automorphism group. From these generators, the full automorphism group can easily be constructed. Using the bliss API was easy and straightforward (see permutation.cpp below). Using inositol as example again, bliss gives 2 generators:&lt;br /&gt;&lt;br /&gt;Generator: 1 6 5 4 3 2 7 12 11 10 9 8 &lt;br /&gt;Generator: 2 3 4 5 6 1 12 7 8 9 10 11 &lt;br /&gt;&lt;br /&gt;Next the generators' inverses and all possible products can be added. This is repeated until all automorphisms are found. [note: the matrix equation doesn't have to be used, the inverse and products are always part of the automorphism group too -- don't forget the identity permutation :-) ]&lt;br /&gt;&lt;br /&gt;The final 12 automorphisms constructed from the given generators are :&lt;br /&gt;&lt;br /&gt;1 2 3 4 5 6 7 8 9 10 11 12 &lt;br /&gt;1 6 5 4 3 2 7 12 11 10 9 8 &lt;br /&gt;2 3 4 5 6 1 12 7 8 9 10 11 &lt;br /&gt;6 1 2 3 4 5 8 9 10 11 12 7 &lt;br /&gt;2 1 6 5 4 3 12 11 10 9 8 7 &lt;br /&gt;6 5 4 3 2 1 8 7 12 11 10 9 &lt;br /&gt;5 4 3 2 1 6 9 8 7 12 11 10 &lt;br /&gt;4 3 2 1 6 5 10 9 8 7 12 11 &lt;br /&gt;3 2 1 6 5 4 11 10 9 8 7 12 &lt;br /&gt;5 6 1 2 3 4 9 10 11 12 7 8 &lt;br /&gt;4 5 6 1 2 3 10 11 12 7 8 9 &lt;br /&gt;3 4 5 6 1 2 11 12 7 8 9 10&lt;br /&gt;&lt;br /&gt;This whole computation takes .019s here :-D&lt;br /&gt;&lt;br /&gt;The code for the example can be found here: &lt;a href="http://pastebin.com/fc45501"&gt;permutation.h&lt;/a&gt; &amp; &lt;a href="http://pastebin.com/f6951a7a6"&gt;permutation.cpp&lt;/a&gt; (requires OB trunk + libbliss)&lt;br /&gt;&lt;br /&gt;In the next post, these automorphisms will be used to construct the signed permutation matrix to finally identify identical stereoisomers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-3552513943200088952?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/3552513943200088952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=3552513943200088952' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3552513943200088952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3552513943200088952'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/09/automorphism-group-bliss.html' title='The automorphism group &amp; bliss'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vRYlXAlReRw/SsJF3GYxkhI/AAAAAAAAAC8/0_FcEhPIeHo/s72-c/inositol.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-6108083282283477967</id><published>2009-09-16T11:14:00.001-07:00</published><updated>2009-09-16T11:30:41.285-07:00</updated><title type='text'>Molsketch: Reaction &amp; Mechanism arrows</title><content type='html'>Here is a short screencast showing some of the new features in Molsketch. First, there are the reaction and mechanism arrows. While there are only two major types of arrows, double clicking an arrow in move mode will bring up a dialog that allows you to change the arrow's appearance.&lt;br /&gt;&lt;br /&gt;The second new feature is the .msk file format. Since it is actually cml, it will likely be renamed to cml later. Apart from the molecules, the format also saves the atom/bond colours and both types of arrows.&lt;br /&gt;&lt;br /&gt;&lt;object height="340" width="560"&gt;&lt;param name="movie" value="http://www.youtube.com/v/61h4zvGyxXc&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/61h4zvGyxXc&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="340" width="560"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;If I find some time in the near future, I will make a release and build a windows installer so windows users can try it out without going through the difficult build process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-6108083282283477967?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/6108083282283477967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=6108083282283477967' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/6108083282283477967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/6108083282283477967'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/09/molsketch-reaction-mechanism-arrows.html' title='Molsketch: Reaction &amp; Mechanism arrows'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-6626722161751626880</id><published>2009-09-16T03:41:00.000-07:00</published><updated>2009-09-16T08:01:56.571-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symmetry permutation automorphism stereochemistry'/><title type='text'>More para-stereocenters, permutation groups and the automorphism group</title><content type='html'>&lt;a href="http://depth-first.com/articles/2009/09/15/stereoisomer-generation"&gt;Rich Apodaca recently blogged&lt;/a&gt; about this stereochemistry related series of posts. He correctly pointed out that the automorphism group lies at the heart of the Razinger paper on stereoismer generation. However, before the automorphism group can be used, all stereocenters have to be found.&lt;br /&gt;&lt;br /&gt;In a &lt;a href="http://timvdm.blogspot.com/2009/09/as-promised-here-are-some-molecules.html"&gt;previous post&lt;/a&gt; I briefly described rule 1 and gave some examples. Below are more examples of these para-stereocenters identified by applying rule 1. As you will notice, most of these structures contain no stereocenter and are used to avoid false positives in the unit tests.&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vRYlXAlReRw/SrDLcvLbUrI/AAAAAAAAACM/VcN15Vp_ZdA/s1600-h/obtest1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 207px;" src="http://4.bp.blogspot.com/_vRYlXAlReRw/SrDLcvLbUrI/AAAAAAAAACM/VcN15Vp_ZdA/s320/obtest1.png" alt="" id="BLOGGER_PHOTO_ID_5382025249268912818" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;While rule 1 handles interdependant stereocenters for cycles, both rule 2 and rule 3 handle individual stereocenters and can be applied directly (rule 1 is applied recursively). The rules can schematically be summarized as:&lt;br /&gt;&lt;br /&gt;2) tetracoordinate carbon is para-stereocenter if it attached:&lt;br /&gt;2a) 1 or 2 pairs of identical symmetry classes (e.g. 1123, 1122), each pair contains at least :&lt;br /&gt;2a') &gt;= 1 true-stereocenter (have 4 different symmetry classes)  -- or --&lt;br /&gt;2a") &gt;= 2 para-stereocenters (from rule 1)&lt;br /&gt;2b) 3 or 4 identical symmetry classes (e.g. 1112, 1111), duplicated symmetry class ligand contains:&lt;br /&gt;2b') &gt;= 2 true-stereocenters -- or --&lt;br /&gt;2b") &gt;= 2 separate assemblies (merged rings) with each &gt;= 2 para-stereocenters&lt;br /&gt;&lt;br /&gt;3) double bond is para-stereocenter if terminal with identical symmetry classes contains at least:&lt;br /&gt;3') &gt;= 1 true-stereocenter&lt;br /&gt;3") &gt;= 2 para-stereocenters&lt;br /&gt;&lt;br /&gt;Some examples of rule 2 &amp;amp; 3:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/SrDU6YLbjnI/AAAAAAAAACU/uTjVs-I_dxo/s1600-h/razinger2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 209px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/SrDU6YLbjnI/AAAAAAAAACU/uTjVs-I_dxo/s320/razinger2.png" alt="" id="BLOGGER_PHOTO_ID_5382035654095638130" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Now that all stereocenters are found, a (very) short introduction to permutations and permutation groups will help us get to the automorphism group (This can be skipped if you are familiar with it). A permutations is simply a reordering of a set of numbers. Although there are several ways to represent permutations, the matrix representation is most useful here. A permutation group is unsurprisingly a group or collection of Permutations. (see Razinger paper + wikipedia &lt;a href="http://en.wikipedia.org/wiki/Permutation_group"&gt;Permutation Group&lt;/a&gt; &amp;amp; &lt;a href="http://en.wikipedia.org/wiki/Permutation_matrix"&gt;Permutation Matrix&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;The automorphism group is a subgroup of the Sn group containing all permutations. Since elements are not allowed to repeat, there will be n! permutations in Sn where n is the number of atoms. In general, the term "auto" means self and permutations belonging to the automorphism group change the atom labeling in such a way that the molecule isn't changed (i.e. no bonds broken or neighbors changed, the molecule remains itself). Mathematically this can be expressed using the adjacency matrix (A) and the permutation matrix (P) in the equation:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/SrD9nogeHRI/AAAAAAAAAC0/qVhXxAIuCGs/s1600-h/PAPA.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 81px; height: 17px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/SrD9nogeHRI/AAAAAAAAAC0/qVhXxAIuCGs/s320/PAPA.png" alt="" id="BLOGGER_PHOTO_ID_5382080412038077714" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;While a brute force check of all n! permutations would work for small molecules, it is not efficient enough for use with most drug-like molecules. To limit the number of automorphism candidates, symmetry classes can be used to provide an initial partitioning. Atoms with identical symmetry class are said to be in the same orbit. Only permutations within orbits are allowed (i.e. to be part automorphism group). These intra-orbit permutations can easily be computed in c++ using std::&lt;a href="http://www.sgi.com/tech/stl/next_permutation.html"&gt;next_permutation&lt;/a&gt;. These intra-orbit permutations are all candidates for the automorphism group (G) and will be added to G if the equation holds (duplicates are ignored, especially the identity permutation will be duplicated many times).&lt;br /&gt;&lt;br /&gt;Next, all inter-orbit permutations still need to be considered. This is achieved by "multiplying" the permutations (I used matrix multiplication but other methods are possible) and this gives rise to a new set of candidates which are also checked using the equation. All permutations in G now make up the automorphism group.&lt;br /&gt;&lt;br /&gt;Below are 3 examples to illustrate how these "obrits" limit the number of permutations. The structure on the left, has 2 orbits, each containing 2 atoms. This structures' Sn group has 7! or 5040 permutations. Using the orbits we can reduce the number of candidates to 2! x 2! = 4. The structure in the middle also has 2 orbits but one orbit has 2 atoms and the other has 4 (6! = 720 -&gt; 2! x 4! = 48). The structure on the right has 3 orbits, each containing 2 atoms (9! = 362880 -&gt; 2! x 2! x 2! = 8).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/SrD120tDyDI/AAAAAAAAACs/n8o4ub-GzxI/s1600-h/orbits.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 122px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/SrD120tDyDI/AAAAAAAAACs/n8o4ub-GzxI/s320/orbits.png" alt="" id="BLOGGER_PHOTO_ID_5382071876917119026" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;While OpenBabel doesn't have code to compute the automorphism group yet, &lt;a href="http://pastebin.com/f1e7cc4f9"&gt;here is some proof of concept code &lt;/a&gt;which will be integrated later. It also contains a method to compute all permutations of the Sn group which can be used in combination with small molecules to validate the automorphism group generating algorithm.&lt;br /&gt;&lt;br /&gt;Once the stereocenters are identified and the automorphism group has been found, this information can be used to eventually create a stereoparity matrix. The details  and code will follow in a later post but knowing that duplicate rows in this matrix represent the same stereoisomer should be motivating :-)  (for both stereoisomer generation &amp;amp; canonicalization)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-6626722161751626880?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/6626722161751626880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=6626722161751626880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/6626722161751626880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/6626722161751626880'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/09/more-para-stereocenters-permutation.html' title='More para-stereocenters, permutation groups and the automorphism group'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_vRYlXAlReRw/SrDLcvLbUrI/AAAAAAAAACM/VcN15Vp_ZdA/s72-c/obtest1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-8706930016468340104</id><published>2009-09-11T13:52:00.000-07:00</published><updated>2009-09-11T14:10:09.908-07:00</updated><title type='text'></title><content type='html'>As &lt;a href="http://timvdm.blogspot.com/2009/09/symmetry-classes-how-to-get-them-and.html"&gt;promised&lt;/a&gt;, here are some molecules with stereogenic units that are considered "hard" to detect. As can be seen from the image, the previous definition of atoms having four different neighbours (by comparing symmetry classes) doesn't always work. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/Sqq7bCLQp3I/AAAAAAAAAB8/F9Lhgkw3D80/s1600-h/stereo2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 238px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/Sqq7bCLQp3I/AAAAAAAAAB8/F9Lhgkw3D80/s320/stereo2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5380318777962440562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The term para-stereocenter is used and adopted for these cases.[1] In general para means ressemble, so para-stereocenters ressemble true-stereocenters but there are differences. The most important difference is that para-stereocenters depend on each other to be stereogenic. In fact this is rule 1 from the Razinger paper:&lt;br /&gt;&lt;br /&gt;&lt;li&gt;rule1: para-stereocenters are assigned to be stereogenic if there are at least two of them in a ring assemblage (single ring, sharing atom/bond, bridged, ...). In OpenBabel code this is called mergedRings but it basically means the same thing.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;This simple rule allows all stereocenters to be found in the given examples. There is also a rule 2 and 3 but these will be covered in the following posts. Still need to commit the code for rule1 later tonight.&lt;br /&gt;&lt;br /&gt;[1] M. Razinger, K. Balasubramanian, M. Perdih, M. E. Munk,&lt;br /&gt;Stereoisomere Generation in Computer-Enhanced Structure Elucidation,&lt;br /&gt;J. Chem. Inf. Comput. Si. 1993, 33, 812-825&lt;br /&gt;&lt;a href="http://www.mcs.csueastbay.edu/~kbalasub/reprints/282.pdf"&gt;http://www.mcs.csueastbay.edu/~kbalasub/reprints/282.pdf&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-8706930016468340104?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/8706930016468340104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=8706930016468340104' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/8706930016468340104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/8706930016468340104'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/09/as-promised-here-are-some-molecules.html' title=''/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_vRYlXAlReRw/Sqq7bCLQp3I/AAAAAAAAAB8/F9Lhgkw3D80/s72-c/stereo2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-5835142336876922561</id><published>2009-09-11T06:38:00.000-07:00</published><updated>2009-09-11T07:26:06.955-07:00</updated><title type='text'>Symmetry classes: How to get them and what to do with them</title><content type='html'>For a long time, I've wanted to make a series of blog posts about my stereochemistry adventures. This is post will mainly be about symmetry but we'll get to it's relationship to stereochemistry at the end. In this post (and the following), symmetry will always mean topological symmetry (or graph symmetry). This doesn't imply any 3D orientation or special symmetry. For example, below is an image with symmetry classes assigned to the atoms (click to enlarge):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/SqpUcMRQPgI/AAAAAAAAABc/gfAX396Rk_8/s1600-h/symmetry1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 262px; height: 320px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/SqpUcMRQPgI/AAAAAAAAABc/gfAX396Rk_8/s320/symmetry1.png" alt="" id="BLOGGER_PHOTO_ID_5380205548154142210" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Perhaps, a better title would have been "... and what to do with them &lt;span style="font-weight: bold;"&gt;in the first place&lt;/span&gt;" but this seemed too long. However, to motivate my readers, I'll start by answering the second question. In OpenBabel we currently use the symmetry classes to identify stereogenic units (i.e. tetrahedral atoms, cis/trans double bonds, ...). For example, if an atom contains neighbors with 4 distinct symmetry classes, the atom is considered to be chiral or stereogenic. There are exceptions to this which will be discussed in later posts.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/SqpddGrRWcI/AAAAAAAAAB0/lhB3tKh39rY/s1600-h/stereo1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 137px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/SqpddGrRWcI/AAAAAAAAAB0/lhB3tKh39rY/s320/stereo1.png" alt="" id="BLOGGER_PHOTO_ID_5380215459437173186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A second and perhaps more useful everyday example is to determine how many peaks there should be in an 13C-NMR spectrum. Since carbon atoms in the same symmetry class will be in a similar environment, their chemical shifts will be similar. In the example below, you can clearly see that there are 8 different carbon symmetry classes. Two classes have more than one atom and correctly show the symmetry (6 &amp;amp; 8). The spectrum taken from wikipedia doesn't hve a hight enough resolution but the peaks should be there :-)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/SqpYdn4s6eI/AAAAAAAAABs/zYyuV5R9KEY/s1600-h/propylbenzoate.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 268px; height: 160px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/SqpYdn4s6eI/AAAAAAAAABs/zYyuV5R9KEY/s320/propylbenzoate.png" alt="" id="BLOGGER_PHOTO_ID_5380209970793736674" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/b/ba/DEPT_spectra.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 575px; height: 307px;" src="http://upload.wikimedia.org/wikipedia/en/b/ba/DEPT_spectra.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For H-NMR this is slightly more complex due to stronger coupling.&lt;br /&gt;&lt;br /&gt;Computing the symmetry classes is actually not that hard. The most common method use is the Morgan's Extended Connectivity (EC) algorithm:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Assign each atom it's degree as starting point&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Iterator over the atoms and assign the summed values for each atom's neighbors to it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Repeat untill the number of distinct classes remains the same for two iterations.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;The degree is the Graph Invariant (GI) here. In reality OpenBabel uses another GI with more discriminating power to avoid isospectral points (i.e. points with the same symmetry class which are not symmetric) but the principle remains the same. The symmetry classes are also renumbered so they are all within 1 ... n (# symmetry classes).&lt;br /&gt;&lt;br /&gt;Next post will be about the identification of stereocenters for symmetrical molecules.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-5835142336876922561?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/5835142336876922561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=5835142336876922561' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/5835142336876922561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/5835142336876922561'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/09/symmetry-classes-how-to-get-them-and.html' title='Symmetry classes: How to get them and what to do with them'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_vRYlXAlReRw/SqpUcMRQPgI/AAAAAAAAABc/gfAX396Rk_8/s72-c/symmetry1.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-8717737508834857865</id><published>2009-09-11T05:56:00.000-07:00</published><updated>2009-09-11T06:10:10.784-07:00</updated><title type='text'>Avogadro 0.9.8</title><content type='html'>Avogadro 0.9.8 was released yesterday and the windows installer including the python bindings and dependencies is available from &lt;a href="https://sourceforge.net/projects/avogadro/files/"&gt;sourceforge&lt;/a&gt;. There are no big new features but several bugs are fixed including some problems with translations. Accents were not displayed correctly and it had something to do with the encoding (UTF-8) of the files but we found a solution and Avogadro looks fine in French.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vRYlXAlReRw/SqpL9f0gYRI/AAAAAAAAABU/Wco03ns9Dgs/s1600-h/Windows+XP+Home+Edition+%40+2009-09-11+15:10:23.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 180px;" src="http://2.bp.blogspot.com/_vRYlXAlReRw/SqpL9f0gYRI/AAAAAAAAABU/Wco03ns9Dgs/s320/Windows+XP+Home+Edition+%40+2009-09-11+15:10:23.png" alt="" id="BLOGGER_PHOTO_ID_5380196224733307154" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-8717737508834857865?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/8717737508834857865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=8717737508834857865' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/8717737508834857865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/8717737508834857865'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/09/avogadro-098.html' title='Avogadro 0.9.8'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vRYlXAlReRw/SqpL9f0gYRI/AAAAAAAAABU/Wco03ns9Dgs/s72-c/Windows+XP+Home+Edition+%40+2009-09-11+15:10:23.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-668666226845290316</id><published>2009-09-07T10:53:00.000-07:00</published><updated>2009-09-07T11:15:52.345-07:00</updated><title type='text'>Molsketch</title><content type='html'>&lt;object height="505" width="853"&gt;The last 2 months Nicola Zonta and I have been working on improving Molsketch. While development is still at an early stage and bugs may be present, great progress has been made. Nicola released a version called Zem to go together with the 3D Zodiac program.&lt;br /&gt;&lt;br /&gt;If you want to try it out, a windows installer is available on &lt;a href="http://www.zeden.org/"&gt;zeden.org&lt;/a&gt;. Linux users can get the current development code for molsketch at my &lt;a href="http://github.com/timvdm/Molsketch"&gt;github&lt;/a&gt;&lt;/object&gt; page. &lt;span style="font-weight: bold;"&gt;NOTE&lt;/span&gt;: requires OpenBabel trunk: &lt;code&gt;svn co https://openbabel.svn.sourceforge.net/svnroot/openbabel/openbabel/trunk&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The zem release doen't include the latest features yet but here is a screencast made with the current github version of molsketch. The big difference with zem 0.3 is the ItemPlugin concept which is illustrated in the screencast. The idea is that more of these plugins can be added. While I don't have an example of this yet I intend to make it possible to use REST API's in this way.&lt;br /&gt;&lt;br /&gt;Feel free to make suggestions, propose ideas, file bugs, contribute, etc.&lt;br /&gt;&lt;br /&gt;&lt;object height="505" width="853"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Aw4aOp5eXqM&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/Aw4aOp5eXqM&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="505" width="853"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-668666226845290316?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/668666226845290316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=668666226845290316' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/668666226845290316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/668666226845290316'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/09/molsketch.html' title='Molsketch'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-5087435709347573432</id><published>2009-07-19T18:05:00.000-07:00</published><updated>2009-07-19T18:19:07.431-07:00</updated><title type='text'>SourceForge's Community Choise Awards</title><content type='html'>I'm pleased with Avogadro's nomination for SourceForge's Community Choise Awards. First of all, thanks to all people who have voted to get us nominated. Secondly, thanks to those who have already voted for the final. For those who haven't voted yet, voting ends July 21st. This is your last chance! :-)&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://sf.net/community/cca09/vote/?f=386"&gt;Vote Now!&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;We've also made windows installer packages for the 0.9.7 release. These are already on sourceforge. The official realease mail etc. will follow soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-5087435709347573432?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/5087435709347573432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=5087435709347573432' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/5087435709347573432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/5087435709347573432'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/07/sourceforges-community-choise-awards.html' title='SourceForge&apos;s Community Choise Awards'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-7798021624787981837</id><published>2009-05-16T14:58:00.000-07:00</published><updated>2009-05-16T15:57:11.355-07:00</updated><title type='text'>Using the Avogadro library from python</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/Sg8411LEIJI/AAAAAAAAABM/p6Ed5t2TSIM/s1600-h/standalone.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/Sg8411LEIJI/AAAAAAAAABM/p6Ed5t2TSIM/s320/standalone.png" alt="" id="BLOGGER_PHOTO_ID_5336546580915036306" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;As we get closer to &lt;a href="http://avogadro.openmolecules.net"&gt;Avogadro&lt;/a&gt; 1.0, the python bindings are becoming more and more powerful. For example, take this small script (65 lines) which allows large files to be read in a separate thread. Once the file is read, clicking a title in the list will open a 3D subwindow with the molecule. Scripts like this could be used to preview various molecules, setup a very basic application for educational purposes etc.&lt;br /&gt;&lt;br /&gt;Note: Requires Avogadro developer version (next release will probably be in two weeks)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-7798021624787981837?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/7798021624787981837/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=7798021624787981837' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/7798021624787981837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/7798021624787981837'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/05/using-avogadro-library-from-python.html' title='Using the Avogadro library from python'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_vRYlXAlReRw/Sg8411LEIJI/AAAAAAAAABM/p6Ed5t2TSIM/s72-c/standalone.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-1251450256758695184</id><published>2009-04-28T08:52:00.000-07:00</published><updated>2009-04-28T09:38:31.162-07:00</updated><title type='text'>SxsTrace, making Manifest-Hell more bearable</title><content type='html'>For people comming from unix, Microsoft's side-by-side (SxS) assemblies can be annoying to say the least. The term &lt;a href="http://blog.cryos.net/archives/209-Manifest-Hell...The-New-DLL-Hell.html"&gt;Manifest-Hell&lt;/a&gt;, DLL-Hell's successor, is often used to describe various SxS problems.&lt;br /&gt;&lt;br /&gt;It's not that we are complaining just because it is a microsoft product. The main problem is the cryptic error messages you get when you first encounter it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vRYlXAlReRw/SfcsBr7_Z0I/AAAAAAAAAA8/E0sod4gqL-A/s1600-h/error1.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 136px;" src="http://3.bp.blogspot.com/_vRYlXAlReRw/SfcsBr7_Z0I/AAAAAAAAAA8/E0sod4gqL-A/s320/error1.png" alt="" id="BLOGGER_PHOTO_ID_5329777091502106434" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vRYlXAlReRw/SfcsWWqusAI/AAAAAAAAABE/UheEq-339xw/s1600-h/error2.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 74px;" src="http://1.bp.blogspot.com/_vRYlXAlReRw/SfcsWWqusAI/AAAAAAAAABE/UheEq-339xw/s320/error2.png" alt="" id="BLOGGER_PHOTO_ID_5329777446569816066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The good news is that there is a tool called &lt;a href="http://blogs.msdn.com/junfeng/archive/2006/04/14/576314.aspx"&gt;SxsTrace&lt;/a&gt; to debug these issues. It generates a detailed logfile containing all info you need. It even gives the linenumber in the manifest file where the error is found. Using SxsTrace, creating your own assemblies becomes easy :-) This makes me wonder why this tool isn't mentioned more in docs... Unfortunually there is also bad news, the SxsTrace tool is only found on windows vista (newer sxs.dll). Altough I'm happy I have vista now, I still wonder how XP users are supposed to fix these problems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-1251450256758695184?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/1251450256758695184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=1251450256758695184' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/1251450256758695184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/1251450256758695184'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2009/04/sxstrace-making-manifest-hell-more.html' title='SxsTrace, making Manifest-Hell more bearable'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_vRYlXAlReRw/SfcsBr7_Z0I/AAAAAAAAAA8/E0sod4gqL-A/s72-c/error1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-3416500265221666050</id><published>2008-12-06T12:55:00.000-08:00</published><updated>2008-12-06T16:10:05.181-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SIP'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='boost'/><category scheme='http://www.blogger.com/atom/ns#' term='Qt'/><title type='text'>Avogadro gets new python wrappers</title><content type='html'>The past week I've been very busy creating new python wrappers for &lt;a href="http://avogadro.openmolecules.net/wiki/Main_Page"&gt;Avogadro&lt;/a&gt;. About 70% of the classes have been wrapped and have associated unit tests to make sure the wrappings work.&lt;br /&gt;&lt;br /&gt;We use &lt;a href="http://www.boost.org/doc/libs/1_37_0/libs/python/doc/index.html"&gt;boost::python&lt;/a&gt; to expose our classes to python and also use it to help with the embedding. However, there were several hurdles to overcome before the python bindings allowed us to do everything from python. In this post I'll summarize each of them and I hope this information may be useful for other people in a similar situation.&lt;br /&gt;&lt;br /&gt;To start simple, I added to/from python array converters for &lt;a href="http://eigen.tuxfamily.org"&gt;Eigen&lt;/a&gt;, the template library we use for all our math. In python, the users can just use arrays from the numpy package to get/set atom positions, do rotations, ....&lt;br /&gt;&lt;blockquote&gt;example:&lt;br /&gt;&gt;&gt;&gt; import Avogadro&lt;br /&gt;&gt;&gt;&gt; from numpy import *&lt;br /&gt;&gt;&gt;&gt; molecule = Avogadro.molecule&lt;br /&gt;&gt;&gt;&gt; atom = molecule.newAtom()&lt;br /&gt;&gt;&gt;&gt; atom.pos = array([1.0, 2.0, 3.0])&lt;br /&gt;&gt;&gt;&gt; print atom.pos&lt;br /&gt;[1.  2.  3.]&lt;br /&gt;&lt;/blockquote&gt;Now, it gets more interesting, we also use &lt;a href="http://doc.trolltech.com/4.4"&gt;Qt&lt;/a&gt; and although using &lt;a href="http://www.riverbankcomputing.com/static/Docs/sip4/sipref.html"&gt;SIP&lt;/a&gt; is an obvious option, I recently started to love boost:python and thought there had to be a way. Searching the web I found &lt;a href="http://www.diotavelli.net/PyQtWiki/BoostPythonIntegration"&gt;this&lt;/a&gt;, while the described situation may apply to some cases, the approach uses both boost::python and SIP to do the wrapping and makes SIP aware of boost::python. For Avogadro we need the reverse, all wrapping needs to be done by boost::python and our functions have to able to return and accept PyQt objects. Another search result was the documentation page of &lt;a href="http://www.slac.stanford.edu/grp/ek/hippodraw/pythonoverview_root.html"&gt;HippoDraw&lt;/a&gt;. They seem to have had the same problem but just used SIP. The page also mentions &lt;a href="http://www.nabble.com/how-to-return-arbitrary-%28python-%29objects-from-boost--td16853297.html"&gt;a discussion on the Python sig-c++&lt;/a&gt; mailing list. Since these are the top results, I assume this an unexplored area. I would love to see how other projects have solved this, please let me know if you find any.&lt;br /&gt;&lt;br /&gt;Anyway, after some hacking, Avogadro's python module is now able to return and accept real PyQt wrapped objects. For example, the Tool class is wrapped using::boost python, when you call&lt;br /&gt;&lt;blockquote&gt;QWidget* Tool::settingsWidget();&lt;/blockquote&gt;you get a real PyQt object with all it's functions available etc...&lt;br /&gt;&lt;blockquote&gt;&gt;&gt;&gt; print tool&lt;br /&gt;&amp;lt;Avogadro.Tool object at 0x94e06f4&amp;gt;&lt;br /&gt;&gt;&gt;&gt; print tool.settingsWidget&lt;br /&gt;&amp;lt;PyQt4.QtGui.QWidget object at 0xb5b73d6c&amp;gt;&lt;/blockquote&gt;The following is also possible:&lt;br /&gt;&lt;blockquote&gt;void GLWidget::setUndoStack( QUndoStack *undoStack )&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; glwidget = Avogadro.GLWidget()&lt;br /&gt;&gt;&gt;&gt; print glwidget&lt;br /&gt;&amp;lt;Avogadro.GLWidget object at 0x93f8d24&amp;gt;&lt;br /&gt;&gt;&gt;&gt; undostack = QUndoStack()&lt;br /&gt;&gt;&gt;&gt; print undostack&lt;br /&gt;&amp;lt;PyQt4.QtGui.QUndoStack object at 0x956daec&amp;gt;&lt;br /&gt;&gt;&gt;&gt; glwidget.undoStack = undostack&lt;/blockquote&gt;So far so good, but there are still some things missing. For example how would you resize the GLWidget (our main view widget)? One option would be to just add boost::python definitions for the ones you think will be needed. However, seen how big Qt is, this does not scale very well. While I'd like to keep everything as simple as possible for the python users, I added a conversion function that allows us to convert a boost::python wrapped class to the relevant PyQt wrapped object. For our GLWidget class, this would be QGLWidget.&lt;br /&gt;&lt;br /&gt;another example:&lt;br /&gt;&gt;&gt;&gt; print glwidget&lt;br /&gt;&amp;lt;Avogadro.GLWidget object at 0x9da6d24&amp;gt;&lt;br /&gt;&gt;&gt;&gt; print Avogadro.toPyQt(glwidget)&lt;br /&gt;&amp;lt;PyQt4.QtOpenGL.QGLWidget object at 0x9f167ac&amp;gt;&lt;br /&gt;&gt;&gt;&gt; Avogadro.toPyQt(glwidget).resize(640, 480)&lt;br /&gt;&gt;&gt;&gt; Avogadro.toPyQt(glwidget).show()&lt;br /&gt;&lt;br /&gt;The toPyQt(...) function does not only allow us to use PyQt defined functions on our own classes, it also gives us signals/slots for free:&lt;br /&gt;&lt;blockquote&gt;from PyQt4.Qt import *&lt;br /&gt;import Avogadro&lt;br /&gt;import sys&lt;br /&gt;&lt;br /&gt;class MyClass(QObject):&lt;br /&gt;  def __init__(self):&lt;br /&gt;    QObject.__init__(self)&lt;br /&gt;&lt;br /&gt;  @pyqtSignature("")&lt;br /&gt;  def printHelloWorld(self):&lt;br /&gt;    print "Hello World"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;app = QApplication(sys.argv) # PyQt wrapped object&lt;br /&gt;&lt;br /&gt;button = QPushButton() # PyQt wrapped object&lt;br /&gt;button.show()&lt;br /&gt;&lt;br /&gt;molecule = Avogadro.Molecule() # boost:python wrapped object&lt;br /&gt;&lt;br /&gt;myClass = MyClass() # real python class&lt;br /&gt;&lt;br /&gt;# connect the signals&lt;br /&gt;QObject.connect(button, SIGNAL("clicked()"), Avogadro.toPyQt(molecule), SIGNAL("updated()"))&lt;br /&gt;QObject.connect(Avogadro.toPyQt(molecule), SIGNAL("updated()"), myClass, SLOT("printHelloWorld()"))&lt;br /&gt;&lt;br /&gt;sys.exit(app.exec_())&lt;/blockquote&gt;Everytime you press the button, the signal is routed trhough a boost::python wrapped class and "Hello World" is printed :-)&lt;br /&gt;&lt;br /&gt;That's all for now. More posts will follow demonstrating more cool python stuff and don't forget to check out the &lt;a href="http://blog.cryos.net/"&gt;eye-candy Marcus&lt;/a&gt; has recently added to Avogadro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-3416500265221666050?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/3416500265221666050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=3416500265221666050' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3416500265221666050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/3416500265221666050'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2008/12/avogadro-gets-new-python-wrappers.html' title='Avogadro gets new python wrappers'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-862270798083055781</id><published>2008-04-30T12:39:00.000-07:00</published><updated>2008-04-30T13:15:18.942-07:00</updated><title type='text'>Upcomming OpenBabel 2.2 release</title><content type='html'>OpenBabel 2.2 will be released soon. In the past 9 months since the 2.1.1 release, the force field code has really improved.&lt;br /&gt;&lt;br /&gt;Two new force fields are available in 2.2. The first is MMFF94, a force field that can be used for drug like molecules and ligand-protein interactions. Although this force field could be used for proteins themselves, protein specific ones like AMBER would be more suited, especially for performance reasons. The implementation is validated using the &lt;a href="http://www.ccl.net/cca/data/MMFF94/"&gt;MMFF94 validation suite&lt;/a&gt; and the results are available &lt;a href="http://home.scarlet.be/timvdm/MMFF94_validation_output.gz"&gt;here&lt;/a&gt;. Some special cases remain problematic such as bridged rings and emperical rules when parameters are missing. However, the errors are so small and rare that it is suited for most applications.&lt;br /&gt;&lt;br /&gt;The second new force field, implemented by &lt;a href="http://geoffhutchison.net/blog/"&gt;Geoff&lt;/a&gt;, is UFF. This force field has parameters for the entire periodic system and is therefore a valuable addition to the list. Bob Hanson has also ported UFF from openbabel to JMol. Towards OB 3.0 a biomolecule force field like AMBER will probably be added.&lt;br /&gt;&lt;br /&gt;Another great improvement is the performance. The numbers on the &lt;a href="http://openbabel.org/wiki/Molecular_mechanics#Performance"&gt;updated wiki page&lt;/a&gt; speak for themselves. Minimizations run about 100 times faster!&lt;br /&gt;&lt;br /&gt;This will be the first release with the OBBuilder class. This allows openbabel to generate 3D coordinates with a fragment based approach. The database with fragments was derived from &lt;a href="http://zinc.docking.org/"&gt;Zinc database&lt;/a&gt; by  &lt;a href="http://geoffhutchison.net/blog/"&gt;Geoff&lt;/a&gt;. Stereochemistry will not be taken into account for now, but it's a great start.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-862270798083055781?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/862270798083055781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=862270798083055781' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/862270798083055781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/862270798083055781'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2008/04/upcomming-openbabel-22-release.html' title='Upcomming OpenBabel 2.2 release'/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2980252964491090926.post-5138552740414406587</id><published>2008-01-01T13:33:00.000-08:00</published><updated>2008-01-01T13:48:24.492-08:00</updated><title type='text'></title><content type='html'>Hi,&lt;br /&gt;&lt;br /&gt;First of all, I would like to welcome you to my blog. I'm a student farmaceutical science at the University of Antwerp. In my free time I work on the open source projects OpenBabel (&lt;a href="http://openbabel.sourceforge.net/"&gt;http://openbabel.sourceforge.net/&lt;/a&gt;) and avogadro (&lt;a href="http://avogadro.sourceforge.net/"&gt;http://avogadro.sourceforge.net/&lt;/a&gt;). This blog will mainly be about these two projects and their progress.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2980252964491090926-5138552740414406587?l=timvdm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://timvdm.blogspot.com/feeds/5138552740414406587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2980252964491090926&amp;postID=5138552740414406587' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/5138552740414406587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2980252964491090926/posts/default/5138552740414406587'/><link rel='alternate' type='text/html' href='http://timvdm.blogspot.com/2008/01/hi-first-of-all-i-would-like-to-welcome.html' title=''/><author><name>timvdm</name><uri>http://www.blogger.com/profile/03531554975947264532</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
