<?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-8953369623923024563</id><updated>2012-01-31T18:06:26.056-05:00</updated><category term='matplotlib'/><category term='PyCogent'/><category term='Unix'/><category term='Illumina'/><category term='Pretty code'/><category term='Xcode'/><category term='16S rRNA'/><category term='Note to self'/><category term='C'/><category term='phy trees'/><category term='dental project'/><category term='Geometry'/><category term='Bioconductor'/><category term='What we&apos;re eating'/><category term='Instant Cocoa'/><category term='bioinformatics'/><category term='software installs'/><category term='OS X'/><category term='binary'/><category term='homework'/><category term='alignments'/><category term='ctypes'/><category term='Unifrac'/><category term='linear algebra'/><category term='simple Python'/><category term='what we&apos;re reading'/><category term='PyObjC'/><category term='BLAST'/><category term='bayes'/><category term='duly quoted'/><category term='probability'/><category term='motif'/><category term='EMBOSS'/><category term='simulation'/><category term='Qiime'/><category term='distributions'/><category term='simple math'/><category term='sequence models'/><category term='calculus'/><category term='XML'/><category term='ssh'/><category term='book'/><category term='bindings'/><category term='Cython'/><category term='meta'/><category term='what we&apos;re listening to'/><category term='numpy'/><category term='matrix'/><category term='Linux'/><category term='HMM'/><category term='maximum likelihood'/><category term='stats'/><category term='fun'/><category term='command line'/><category term='DNA binding sites'/><category term='RPy2'/><category term='phylogenetics'/><category term='R'/><category term='Xgrid'/><title type='text'>Python for Bioinformatics</title><subtitle type='html'>An impermanent record of adventures learning bioinformatics.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default?start-index=101&amp;max-results=100'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>744</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-5864307163942579591</id><published>2012-01-22T13:51:00.001-05:00</published><updated>2012-01-22T16:51:15.658-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>MathJax</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;Let's follow up on a few previous posts (a &lt;a href="http://telliott99.blogspot.com/2012/01/vector-fun.html"&gt;calculation&lt;/a&gt; of d/dt of the total energy in a gravitational field, a &lt;a href="http://telliott99.blogspot.com/2012/01/typesetting-math.html"&gt;post&lt;/a&gt; about typesetting math, and an introductory &lt;a href="http://telliott99.blogspot.com/2012/01/typesetting-again.html"&gt;exploration&lt;/a&gt; of LaTeX).  I'm grateful for a comment from a reader, with a link to this &lt;a href="http://www.mathjax.org/docs/1.1/start.html#mathjax-cdn"&gt;page&lt;/a&gt;, which makes it pretty clear that, yes, you can use their server to get the script in your pages.&lt;br /&gt;&lt;br /&gt;So that's what we'll do.  I had to modify the LaTeX commands a bit for this but it's mostly the same as &lt;a href="http://telliott99.blogspot.com/2012/01/typesetting-again.html"&gt;before&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;[ UPDATE:  I do see a problem, now.  The script applies to all LaTeX on the page, which if you go to the main page for the blog, includes the previous post...  Just click on the post title, to see the original formatting code. ]&lt;br /&gt;&lt;br /&gt;&lt;script type="text/x-mathjax-config"&gt;   MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}}); &lt;/script&gt; &lt;script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;$\mathbf{F} = m\mathbf{a}= m\ddot{\mathbf{r}}&lt;br /&gt;= m\frac{d^2}{dt^2}\mathbf{r}$&lt;br /&gt;&lt;br /&gt;$\mathbf{F} = -$$\nabla$$V(\mathbf{r})$&lt;br /&gt;&lt;br /&gt;$E = \frac{1}{2}m|\dot{\mathbf{r}}|^2+ V$&lt;br /&gt;&lt;br /&gt;$\frac{d}{dt} E = \frac{d}{dt} ( \frac{1}{2}m&lt;br /&gt;|\dot{\mathbf{r}}|^2 + V )$ $= ?$&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$|\dot{\mathbf{r}}|^2 = |\dot{\mathbf{r}}|&lt;br /&gt;|\dot{\mathbf{r}}| = \dot{\mathbf{r}}&lt;br /&gt;\cdot\dot{\mathbf{r}}$&lt;br /&gt;&lt;br /&gt;$\frac{d}{dt}\frac{1}{2}m|\dot{\mathbf{r}}|^2&lt;br /&gt;= \frac{1}{2}m\frac{d}{dt}(\dot{\mathbf{r}}&lt;br /&gt;\cdot\dot{\mathbf{r}})$$ = m\dot{\mathbf{r}}\cdot\ddot{\mathbf{r}}$$ = \dot{\mathbf{r}}\cdot-($$\nabla$$V$$)$&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$\nabla$$V$ $= &lt; \frac{\partial{V}} {\partial{x}},\frac{\partial{V}} {\partial{y}},\frac{\partial{V}} {\partial{z}} &gt;$&lt;br /&gt;&lt;br /&gt;$\dot{\mathbf{r}}$ = $&lt;$ $\frac{dx}{dt}$,$\frac{dy}{dt}$,$\frac{dz}{dt}$$ &gt;$&lt;br /&gt;&lt;br /&gt;$\nabla$$V$ $\cdot$$\dot{\mathbf{r}}$ $= &lt;\frac{\partial{V}} {\partial{x}} \frac{dx}{dt},\frac{\partial{V}} {\partial{y}} \frac{dy}{dt},\frac{\partial{V}} {\partial{z}}\frac{dz}{dt}&gt;$$=\frac{d}{dt}V$&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$\frac{d}{dt} E = \frac{d}{dt} ( \frac{1}{2}m&lt;br /&gt;|\dot{\mathbf{r}}|^2 + V )$ $= ?$&lt;br /&gt;&lt;br /&gt;$\frac{d}{dt}$E $= \dot{\mathbf{r}}$$\cdot$(-$\nabla$V) + $\nabla$V $\cdot$ $\dot{\mathbf{r}}$ = 0&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-5864307163942579591?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/5864307163942579591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=5864307163942579591' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5864307163942579591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5864307163942579591'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2012/01/mathjax.html' title='MathJax'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1559451367756339356</id><published>2012-01-21T19:37:00.003-05:00</published><updated>2012-01-23T14:43:51.546-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Typesetting, again</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;Here are the equations from the &lt;a href="http://telliott99.blogspot.com/2012/01/vector-fun.html"&gt;last post&lt;/a&gt;, in &lt;a href="http://www.latex-project.org/"&gt;LaTeX&lt;/a&gt;.  It took about two hours, fairly painstaking work, but I think it looks pretty good..&lt;br /&gt;&lt;br /&gt;UPDATE:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/"&gt;Here&lt;/a&gt; is a nice simple reference for LaTeX.  I started with "LaTeX Bootcamp" (&lt;a href="http://www.google.com/url?sa=t&amp;rct=j&amp;q=latex%20boot%20camp&amp;source=web&amp;cd=1&amp;ved=0CDoQFjAA&amp;url=http%3A%2F%2Fscc.stat.ucla.edu%2Fpage_attachments%2F0000%2F0182%2FLaTeX_Bootcamp.pdf&amp;ei=UbgdT42tLciG2gWn1o3jCw&amp;usg=AFQjCNF2tAxKD87MAiVhxRICr-n8NUvW-Q&amp;sig2=RRcMJPXf_AtEnArsBY063Q"&gt;pdf&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-cX9kgJuPTV8/TxthW_Y46lI/AAAAAAAABzs/AVy019SITHw/s1600/Screen%2Bshot%2B2012-01-21%2Bat%2B8.06.56%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="217" src="http://1.bp.blogspot.com/-cX9kgJuPTV8/TxthW_Y46lI/AAAAAAAABzs/AVy019SITHw/s320/Screen%2Bshot%2B2012-01-21%2Bat%2B8.06.56%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;$\mathbf{F} = m\mathbf{a}= m\ddot{\mathbf{r}}&lt;br /&gt;= m\frac{d^2}{dt^2}\mathbf{r}$&lt;br /&gt;&lt;br /&gt;$\mathbf{F} = -$$\nabla$$V(\mathbf{r})$&lt;br /&gt;&lt;br /&gt;$E = \frac{1}{2}m\norm{\dot{\mathbf{r}}}^2+ V$&lt;br /&gt;&lt;br /&gt;$\frac{d}{dt} E = \frac{d}{dt} (\frac{1}{2}m&lt;br /&gt;\norm{\dot{\mathbf{r}}}^2 + V)$&lt;br /&gt;&lt;br /&gt;\hspace*{2em}$ = ?$\\&lt;br /&gt;&lt;br /&gt;$\norm{\dot{\mathbf{r}}}^2 = \norm{\dot{\mathbf{r}}}&lt;br /&gt;\norm{\dot{\mathbf{r}}} = \dot{\mathbf{r}}&lt;br /&gt;\cdot\dot{\mathbf{r}}$&lt;br /&gt;&lt;br /&gt;$\frac{d}{dt}\frac{1}{2}m\norm{\dot{\mathbf{r}}}^2&lt;br /&gt;= \frac{1}{2}m\frac{d}{dt}(\dot{\mathbf{r}}&lt;br /&gt;\cdot\dot{\mathbf{r}})$&lt;br /&gt;&lt;br /&gt;\hspace*{2em}$ = m\dot{\mathbf{r}}\cdot&lt;br /&gt;\ddot{\mathbf{r}}$&lt;br /&gt;&lt;br /&gt;\hspace*{2em}$ = \dot{\mathbf{r}}\cdot-($&lt;br /&gt;$\nabla$$V$$)$\\&lt;br /&gt;&lt;br /&gt;$\nabla$$V$$ = &lt;\frac{\partial{V}} {\partial{x}},\frac{\partial{V}} {\partial{y}},\frac{\partial{V}} {\partial{z}}&gt;$&lt;br /&gt;&lt;br /&gt;$\dot{\mathbf{r}}$ = $&lt;$$\frac{dx}{dt}$,$\frac{dy}{dt}$,$\frac{dz}{dt}$$&gt;$&lt;br /&gt;&lt;br /&gt;$\nabla$$V$$\cdot$$\dot{\mathbf{r}}$$=&lt;\frac{\partial{V}} {\partial{x}} \frac{dx}{dt},\frac{\partial{V}} {\partial{y}} \frac{dy}{dt},\frac{\partial{V}} {\partial{z}}\frac{dz}{dt}&gt;$&lt;br /&gt;&lt;br /&gt;\hspace*{2em}$=\frac{d}{dt}V$\\&lt;br /&gt;&lt;br /&gt;$\frac{d}{dt}$E = $\dot{\mathbf{r}}$$\cdot$(-&lt;br /&gt;$\nabla$V ) + $\nabla$V $\cdot$ $\dot{\mathbf{r}}$ = 0&lt;br /&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1559451367756339356?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1559451367756339356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1559451367756339356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1559451367756339356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1559451367756339356'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2012/01/typesetting-again.html' title='Typesetting, again'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-cX9kgJuPTV8/TxthW_Y46lI/AAAAAAAABzs/AVy019SITHw/s72-c/Screen%2Bshot%2B2012-01-21%2Bat%2B8.06.56%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1827404329393605683</id><published>2012-01-21T10:37:00.001-05:00</published><updated>2012-01-21T19:26:27.005-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Vector fun</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;In Marsden &amp; Tromba's &lt;a href="http://www.amazon.com/Vector-Calculus-Jerrold-Marsden/dp/0716749920/ref=sr_1_1?ie=UTF8&amp;qid=1327159554&amp;sr=8-1"&gt;Vector Calculus&lt;/a&gt;, I found the following problem.  It involves time-derivatives of the position vector r(t), for which we're using the dot notation of the physicists (and &lt;a href="http://en.wikipedia.org/wiki/Newton%27s_notation"&gt;Newton&lt;/a&gt;).  &lt;br /&gt;&lt;br /&gt;In the first panel, we have Newton's second law, then the statement that the force is minus the gradient of the gravitational potential V, followed by a calculation of the total energy in the system.  The problem is to compute d/dt of the energy.  (&lt;a href="http://en.wikipedia.org/wiki/Conservation_of_energy"&gt;hint&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-AMWNs-VnuXk/TxtXX-OBLfI/AAAAAAAABzI/eil7veBQH2Q/s1600/Screen%2Bshot%2B2012-01-21%2Bat%2B7.24.06%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="266" width="320" src="http://2.bp.blogspot.com/-AMWNs-VnuXk/TxtXX-OBLfI/AAAAAAAABzI/eil7veBQH2Q/s320/Screen%2Bshot%2B2012-01-21%2Bat%2B7.24.06%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The answer is given in the last panel, below.  According to the book, it's a "simple calculation."&lt;br /&gt;&lt;br /&gt;The first step is to compute d/dt of the kinetic energy.  We use the formula from above, plus a trick to convert the squared term back to the dot product of dr/dt with itself.  Then we use the chain rule, and finally, the definition of the force in terms of the gradient of the potential.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Z5auHCKZHy0/TxtXYIS7S_I/AAAAAAAABzQ/vE_WICG8Tnw/s1600/Screen%2Bshot%2B2012-01-21%2Bat%2B7.24.14%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="184" width="320" src="http://1.bp.blogspot.com/-Z5auHCKZHy0/TxtXYIS7S_I/AAAAAAAABzQ/vE_WICG8Tnw/s320/Screen%2Bshot%2B2012-01-21%2Bat%2B7.24.14%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Calculation of d/dt of the potential energy puzzled me for quite a while, though it really shouldn't have.  My solution was to work backward from the answer, as shown.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-nZuMjZp3cN4/TxrYmNQ-ISI/AAAAAAAABys/0pgRUzwvIhM/s1600/Screen%2Bshot%2B2012-01-21%2Bat%2B10.18.07%2BAM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="253" width="320" src="http://3.bp.blogspot.com/-nZuMjZp3cN4/TxrYmNQ-ISI/AAAAAAAABys/0pgRUzwvIhM/s320/Screen%2Bshot%2B2012-01-21%2Bat%2B10.18.07%2BAM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;We put the two results together, and notice that they cancel.  Surprise!&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-c4luYQs40pE/TxrYmQLZxyI/AAAAAAAABzA/HzLWg93AkUc/s1600/Screen%2Bshot%2B2012-01-21%2Bat%2B10.18.15%2BAM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="120" width="320" src="http://3.bp.blogspot.com/-c4luYQs40pE/TxrYmQLZxyI/AAAAAAAABzA/HzLWg93AkUc/s320/Screen%2Bshot%2B2012-01-21%2Bat%2B10.18.15%2BAM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1827404329393605683?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1827404329393605683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1827404329393605683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1827404329393605683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1827404329393605683'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2012/01/vector-fun.html' title='Vector fun'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-AMWNs-VnuXk/TxtXX-OBLfI/AAAAAAAABzI/eil7veBQH2Q/s72-c/Screen%2Bshot%2B2012-01-21%2Bat%2B7.24.06%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-5431886300236864124</id><published>2012-01-21T08:19:00.000-05:00</published><updated>2012-01-21T08:19:22.390-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Typesetting math</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;This post is really just a note to myself about something I need to investigate more.  The problem I'd like to solve is how to format mathematical equations for the web.  You can see the caveman approach on most of my posts here, like &lt;a href="http://telliott99.blogspot.com/2012/01/cycloid.html"&gt;this&lt;/a&gt; one.&lt;br /&gt;&lt;br /&gt;I just make a table in html&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&amp;lt;div style="overflow-x: scroll;"&gt;&lt;br /&gt;&amp;lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;br /&gt;&amp;lt;tbody&gt;&lt;br /&gt;&amp;lt;tr&gt;&amp;lt;td&gt;&amp;lt;pre style="font-family: monaco;"&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I like the background color, and vary it depending on whether the content is code or output from a program.&lt;br /&gt;&lt;br /&gt;It might be nice to have something prettier.  So, looking around, I happened across &lt;a href="http://www.mathjax.org/"&gt;MathJax&lt;/a&gt;, and also this &lt;a href="http://holdenweb.blogspot.com/2011/11/blogging-mathematics.html"&gt;post&lt;/a&gt; which explains how to use it on Blogger.&lt;br /&gt;&lt;br /&gt;Here's a screenshot of the example:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-4c8Qc3CSIyE/Txq63Y8GgFI/AAAAAAAAByM/pjNhzebV-uA/s1600/Screen%2Bshot%2B2012-01-21%2Bat%2B8.16.36%2BAM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="136" width="217" src="http://4.bp.blogspot.com/-4c8Qc3CSIyE/Txq63Y8GgFI/AAAAAAAAByM/pjNhzebV-uA/s320/Screen%2Bshot%2B2012-01-21%2Bat%2B8.16.36%2BAM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The method used in the post is to load the script from the mathjax server, but I think what I'm probably supposed to do is direct people to resource on my (nonexistent) server.  OTOH, they link to the post on the mathjax site.  &lt;br /&gt;&lt;br /&gt;What I'll probably do is just look into how to use LateX and then post screenshots.&lt;br /&gt;&lt;br /&gt;Any thoughts?&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-5431886300236864124?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/5431886300236864124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=5431886300236864124' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5431886300236864124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5431886300236864124'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2012/01/typesetting-math.html' title='Typesetting math'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-4c8Qc3CSIyE/Txq63Y8GgFI/AAAAAAAAByM/pjNhzebV-uA/s72-c/Screen%2Bshot%2B2012-01-21%2Bat%2B8.16.36%2BAM.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-2499965111771521622</id><published>2012-01-21T07:15:00.000-05:00</published><updated>2012-01-21T07:15:04.677-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='calculus'/><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Cycloid</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-iIRJQhWUx3Y/Txqpy3f6pvI/AAAAAAAAByA/F6VmxJgLGJA/s1600/Screen%2Bshot%2B2012-01-21%2Bat%2B6.43.31%2BAM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="160" width="320" src="http://2.bp.blogspot.com/-iIRJQhWUx3Y/Txqpy3f6pvI/AAAAAAAAByA/F6VmxJgLGJA/s320/Screen%2Bshot%2B2012-01-21%2Bat%2B6.43.31%2BAM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;While working through the MIT ocw lectures on multi-variable calculus (Prof. Denis Auroux, &lt;a href="http://ocw.mit.edu/courses/mathematics/18-02-multivariable-calculus-fall-2007/"&gt;here&lt;/a&gt;), I particularly enjoyed his discussion about the cycloid.  Above is a graphic from the wikipedia &lt;a href="http://en.wikipedia.org/wiki/Cycloid"&gt;article&lt;/a&gt; (actually the graphic is an animated gif, but I grabbed one of the frames).  The red curve is generated by the motion of a point on the edge of a rolling circle.&lt;br /&gt;&lt;br /&gt;In addition to the beauty of the curve, it turns out that the length and area under the curve have simple values that are relatively easy to calculate.  See wikipedia for the details.&lt;br /&gt;&lt;br /&gt;One thing the article doesn't explain is how to get the "parametrization" for the curve.  This looks hard, but is made easy by using vectors.  It's explained in the second half of Auroux's fifth &lt;a href="http://ocw.mit.edu/courses/mathematics/18-02-multivariable-calculus-fall-2007/video-lectures/lecture-5-parametric-equations/"&gt;lecture&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Another thing the article doesn't explain is how to integrate&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&amp;radic;(2 - 2 cos t)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Start from the double angle formula:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;cos 2s = cos&lt;sup&gt;2&lt;/sup&gt;s - sin&lt;sup&gt;2&lt;/sup&gt;s&lt;br /&gt;cos 2s = 1 - 2 sin&lt;sup&gt;2&lt;/sup&gt;s&lt;br /&gt;2 sin&lt;sup&gt;2&lt;/sup&gt;s = (1 - cos 2s)&lt;br /&gt;2 sin&lt;sup&gt;2&lt;/sup&gt;(t/2) = (1 - cos t)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;It's straightforward from there.&lt;br /&gt;&lt;br /&gt;The Mathworld &lt;a href="http://mathworld.wolfram.com/Cycloid.html"&gt;article&lt;/a&gt; is also quite nice, and references a famous challenge in history, the one which led to this quote (in reference to Newton):&lt;br /&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;"Ah, I know the lion by his paw!"&lt;/font&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-2499965111771521622?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/2499965111771521622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=2499965111771521622' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2499965111771521622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2499965111771521622'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2012/01/cycloid.html' title='Cycloid'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-iIRJQhWUx3Y/Txqpy3f6pvI/AAAAAAAAByA/F6VmxJgLGJA/s72-c/Screen%2Bshot%2B2012-01-21%2Bat%2B6.43.31%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-461625558584911982</id><published>2012-01-10T18:05:00.000-05:00</published><updated>2012-01-10T18:05:56.211-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Pilgrim's progress</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;Lately I've been working (again) on understanding multi-variable calculus.  I always wished I had time to cover this material in college, but I took lots of courses in biochemistry and molecular biology instead.  I wanted to put up the best resources I've found for this so far.&lt;br /&gt;&lt;br /&gt;First, and no surprise, the ocw videos at MIT by Denis Auroux (&lt;a href="http://ocw.mit.edu/courses/mathematics/18-02-multivariable-calculus-fall-2007/"&gt;here&lt;/a&gt;).  I am currently at #25, about to jump off into integrals in 3D space.  (It's my second time to get this far).  This time I think I really have everything under control.  The proof of Green's theorem was perfect, a kind of mathematical satori.&lt;br /&gt;&lt;br /&gt;I also work through everything in Gilbert Strang's &lt;a href="http://ocw.mit.edu/resources/res-18-001-calculus-online-textbook-spring-2005/textbook/"&gt;book&lt;/a&gt; as well.  I need to read carefully there, because he's so concise, but his insight is just incredible.  Check out the proof of the flux version of Green's &lt;a href="http://en.wikipedia.org/wiki/Green%27s_theorem"&gt;theorem&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Two more are recently discovered resources that are especially helpful because they develop everything slowly but completely:&lt;br /&gt;&lt;br /&gt;Paul's lecture &lt;a href="http://tutorial.math.lamar.edu/"&gt;notes&lt;/a&gt;&lt;br /&gt;A beautiful &lt;a href="http://mathinsight.org/"&gt;set&lt;/a&gt; of pages from someone at U Minnesota&lt;br /&gt;&lt;br /&gt;All highly recommended.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-461625558584911982?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/461625558584911982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=461625558584911982' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/461625558584911982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/461625558584911982'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2012/01/pilgrims-progress.html' title='Pilgrim&apos;s progress'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1904303553679789996</id><published>2011-12-14T15:43:00.001-05:00</published><updated>2011-12-14T15:46:37.216-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='calculus'/><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Getting a little help from Newton</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;I've posted here on a number of topics and derivations in fundamental calculus.  This is about finding the derivative for powers of x with negative or fractional exponents.  It seems a trivial proof, until I got stopped in my tracks by the cofactors of the binomial distribution.&lt;br /&gt;&lt;br /&gt;The idea is to find the slope of the curve at x by adding a little bit to x, (x + h), calculating f(x + h), then subtract f(x), and finally divide by h and finding the limit as h gets very small.  It works great for y = x&lt;sup&gt;2&lt;/sup&gt;.  But consider&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;y = x&lt;sup&gt;1/2&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We want to do:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;1/h [(x + h)&lt;sup&gt;1/2&lt;/sup&gt; - x&lt;sup&gt;1/2&lt;/sup&gt;]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;So thinking about the binomial expansion of the x + h term, I'm trying to figure what &lt;i&gt;is&lt;/i&gt; the expansion for the 1/2 power?  I mean, what can "n choose k" mean when n is 1/2?&lt;br /&gt;&lt;br /&gt;The other thing that is a good approach here is to bring x out of the sum as follows&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;(x + h)&lt;sup&gt;1/2&lt;/sup&gt;&lt;br /&gt;= x&lt;sup&gt;1/2&lt;/sup&gt;(1 + h/x)&lt;sup&gt;1/2&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;To expand this, we just remember Newton's super-duper binomial expansion from &lt;a href="http://telliott99.blogspot.com/2010/11/newtons-expansion-of-binomial-and-more.html"&gt;here&lt;/a&gt;.  If the expression is&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;(1 + Q)&lt;sup&gt;m/n&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;the expansion is&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;1 + (m/n)Q + (m/n)((m-n)/2n)Q&lt;sup&gt;2&lt;/sup&gt; + (m/n)((m-n)/2n)((m-2n)/3n)Q&lt;sup&gt;3&lt;/sup&gt; + .. &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We only need the first two terms because Q&lt;sup&gt;2&lt;/sup&gt; is (h/x)&lt;sup&gt;2&lt;/sup&gt; which we will ignore.  So we have for the expansion&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;(1 + h/x)&lt;sup&gt;1/2&lt;/sup&gt;&lt;br /&gt;= 1 + 1/2(h/x)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and the derivative is the limit as h =&amp;gt; 0 of&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;1/h [x&lt;sup&gt;1/2&lt;/sup&gt;(1 + 1/2(h/x)) - x&lt;sup&gt;1/2&lt;/sup&gt;]&lt;br /&gt;= 1/h (1/2 h) 1/x&lt;sup&gt;1/2&lt;/sup&gt;&lt;br /&gt;= 1/2 x&lt;sup&gt;-1/2&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Similarly for m = -2 and n = 1 the first two terms are 1 and -2 and the expansion we need will be&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;(1 + (h/x))&lt;sup&gt;-2&lt;/sup&gt; = &lt;br /&gt;= 1 - 2(h/x)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The derivative is the limit as h =&amp;gt; 0 of&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;1/h [x&lt;sup&gt;-2&lt;/sup&gt; (1 - 2(h/x)) - x&lt;sup&gt;-2&lt;/sup&gt;] =&lt;br /&gt;= 1/h x&lt;sup&gt;-2&lt;/sup&gt; (-2)(h/x)&lt;br /&gt;= -2 x&lt;sup&gt;-3&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Easy when you know how.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1904303553679789996?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1904303553679789996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1904303553679789996' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1904303553679789996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1904303553679789996'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/12/getting-little-help-from-newton.html' title='Getting a little help from Newton'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-2388845502956681642</id><published>2011-12-14T14:39:00.000-05:00</published><updated>2011-12-14T14:39:40.222-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='book'/><title type='text'>Basic Python for Bioinformatics</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;I've been silent online for the last few months, due to other commitments associated with my day job.  But I haven't forgotten all of you in the ether.  &lt;br /&gt;&lt;br /&gt;Just before I got busy, I wrote a book about basic programming with Python using lots of biological examples.  It's been proofed once or twice, but is not quite a beta version, so let's call it the gamma release.  I want to push it out now, even it could certainly use some more polish, because it's not clear when I'll get the time to do that.&lt;br /&gt;&lt;br /&gt;The target audience is the novice programmer who is interested in biology.  However, it differs from most similar material because there are lots of biological and sequence analysis examples, collected from various sources including posts on this site.&lt;br /&gt;&lt;br /&gt;Here is a screenshot of the toc for the middle section of the book.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-MTfNiaNBTLw/Tuj7Wa8500I/AAAAAAAABx0/hMdfONk7mIg/s1600/Screen%2Bshot%2B2011-12-14%2Bat%2B2.38.22%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="158" src="http://1.bp.blogspot.com/-MTfNiaNBTLw/Tuj7Wa8500I/AAAAAAAABx0/hMdfONk7mIg/s320/Screen%2Bshot%2B2011-12-14%2Bat%2B2.38.22%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The book is in html format (&lt;a href="http://dl.dropbox.com/u/3534458/html.zip"&gt;link&lt;/a&gt; to Dropbox zip).  It was built using the &lt;a href="http://sphinx.pocoo.org/"&gt;Sphinx&lt;/a&gt; software.  One can generate a pdf version of the book as well, but it suffers from the major limitation that cut-and-paste of the code loses the indentation.  The version linked to here has code examples that can be pasted directly into a text file and executed, and often will work in the interpreter as well.&lt;br /&gt;&lt;br /&gt;I hope you like it.  I would be very grateful for comments, criticisms, corrections, and even complaints.  Post 'em as comments here, or find my work email through the aboutme.  Enjoy!&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-2388845502956681642?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/2388845502956681642/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=2388845502956681642' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2388845502956681642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2388845502956681642'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/12/basic-python-for-bioinformatics.html' title='Basic Python for Bioinformatics'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-MTfNiaNBTLw/Tuj7Wa8500I/AAAAAAAABx0/hMdfONk7mIg/s72-c/Screen%2Bshot%2B2011-12-14%2Bat%2B2.38.22%2BPM.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7619015056950161625</id><published>2011-08-31T18:23:00.000-04:00</published><updated>2011-08-31T18:23:47.712-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><category scheme='http://www.blogger.com/atom/ns#' term='binary'/><title type='text'>Binary multiplication, again</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;I had a lot of fun this afternoon, but all along I knew I was "reinventing the wheel."  It's easy when you know where you're going.&lt;br /&gt;&lt;br /&gt;I implemented binary multiplication with a class that keeps its data as Python strings like '00100011'.  It's probably because I have been re-reading Charles Petzold's book &lt;a href="http://www.amazon.com/Code-Language-Computer-Hardware-Software/dp/0735611319/ref=sr_1_1?ie=UTF8&amp;qid=1314829206&amp;sr=8-1"&gt;Code&lt;/a&gt;, which I think is a classic.  In any event, I wrote the class "word" which allows objects to add, multiply and exponentiate themselves.  The second file is test.py which exercises the class.&lt;br /&gt;&lt;br /&gt;It's a great "simple Python" coding project.  We do bit-shifting by hand.  If you want to be slick, you could go further by trying to implement &lt;a href="http://en.wikipedia.org/wiki/Exponentiation_by_squaring"&gt;fast exponentiation&lt;/a&gt;.  &lt;a href="http://blog.madpython.com/2010/07/17/algorithms-in-python-binary-operations/"&gt;Here&lt;/a&gt; is another example by a guy who obviously knows what he's doing.&lt;br /&gt;&lt;br /&gt;A bit of sample output:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; python test.py&lt;br /&gt;x     467&lt;br /&gt;y     327&lt;br /&gt;x + y 00000000 00000000 00000011 00011010 = 794&lt;br /&gt;check 467 + 327 = 794&lt;br /&gt;x * y 00000000 00000010 01010100 10000101 = 152709&lt;br /&gt;check 467 * 327 = 152709&lt;br /&gt;z      3&lt;br /&gt;x**z  00000110 00010010 00010010 00001011 = 101847563&lt;br /&gt;check 467 ** 3 = 101847563&lt;br /&gt;&lt;br /&gt;x     995&lt;br /&gt;y     402&lt;br /&gt;x + y 00000000 00000000 00000101 01110101 = 1397&lt;br /&gt;check 995 + 402 = 1397&lt;br /&gt;x * y 00000000 00000110 00011010 01110110 = 399990&lt;br /&gt;check 995 * 402 = 399990&lt;br /&gt;z      3&lt;br /&gt;x**z  00111010 10110111 00001100 10111011 = 985074875&lt;br /&gt;check 995 ** 3 = 985074875&lt;br /&gt;&lt;br /&gt;x     897&lt;br /&gt;y     490&lt;br /&gt;x + y 00000000 00000000 00000101 01101011 = 1387&lt;br /&gt;check 897 + 490 = 1387&lt;br /&gt;x * y 00000000 00000110 10110100 11101010 = 439530&lt;br /&gt;check 897 * 490 = 439530&lt;br /&gt;z      4&lt;br /&gt;x**z  10111011 11001001 10001110 00000001 = 3150548481&lt;br /&gt;ran into a slight problem&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;code&gt;word.py&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;class word:&lt;br /&gt;    SZ = 32&lt;br /&gt;    def __init__(self,n):&lt;br /&gt;        if type(n) == type('a'):&lt;br /&gt;            b = n.rjust(word.SZ,'0')&lt;br /&gt;        elif type(n) == type(1):&lt;br /&gt;            b = bin(n)[2:]&lt;br /&gt;        else:&lt;br /&gt;            raise ValueError, "can't do that"&lt;br /&gt;        self.b = b.rjust(word.SZ,'0')&lt;br /&gt;        &lt;br /&gt;    def __repr__(self):&lt;br /&gt;        b = self.b&lt;br /&gt;        s = ' '.join([b[:8], b[8:16], b[16:24], b[24:]])&lt;br /&gt;        s += ' = ' + str(eval('0b' + self.b))&lt;br /&gt;        return s&lt;br /&gt;        &lt;br /&gt;    def __add__(self, a):&lt;br /&gt;        carry = '0'&lt;br /&gt;        rL = list()&lt;br /&gt;        for i in range(len(self.b)-1,-1,-1):&lt;br /&gt;            x = self.b[i]&lt;br /&gt;            y = a.b[i]&lt;br /&gt;            t = x+y&lt;br /&gt;            if (t == '01' or t == '10'):&lt;br /&gt;                if carry == '0':&lt;br /&gt;                    rL.append('1')&lt;br /&gt;                if carry == '1':&lt;br /&gt;                    rL.append('0')&lt;br /&gt;            elif t == '00':&lt;br /&gt;                rL.append(carry)&lt;br /&gt;                carry = '0'&lt;br /&gt;            else:&lt;br /&gt;                assert t == '11'&lt;br /&gt;                if carry == '0':&lt;br /&gt;                    rL.append('0')&lt;br /&gt;                    carry = '1'&lt;br /&gt;                else:&lt;br /&gt;                    rL.append('1')&lt;br /&gt;                    carry = '1'&lt;br /&gt;        if carry == '1':&lt;br /&gt;            raise ValueError, 'overflow'&lt;br /&gt;        rL.reverse()&lt;br /&gt;        return word(''.join(rL))&lt;br /&gt;    &lt;br /&gt;    def __mul__(self, a):&lt;br /&gt;        L = list()&lt;br /&gt;        for i in range(len(self.b)-1,-1,-1):&lt;br /&gt;            x = self.b[i]&lt;br /&gt;            if not x == '1':&lt;br /&gt;                continue&lt;br /&gt;            n = word.SZ - i - 1&lt;br /&gt;            r = word(a.b[n:] + '0'*(n))&lt;br /&gt;            L.append(r)&lt;br /&gt;        res = L.pop(0)&lt;br /&gt;        #print 'start:       ', res&lt;br /&gt;        while L:&lt;br /&gt;            next = L.pop(0)&lt;br /&gt;            #print 'next:        ', next&lt;br /&gt;            res = res + next&lt;br /&gt;            #if L:&lt;br /&gt;                #print 'intermediate:', &lt;br /&gt;            #else:&lt;br /&gt;                #print 'result:      ',&lt;br /&gt;            #print res&lt;br /&gt;        return res&lt;br /&gt;&lt;br /&gt;    def __pow__(self, n):&lt;br /&gt;        res = self&lt;br /&gt;        for i in range(n-1):&lt;br /&gt;            res = res * self&lt;br /&gt;        return res&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;code&gt;test.py&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;import random&lt;br /&gt;from word import word&lt;br /&gt;        &lt;br /&gt;R = range(1000)&lt;br /&gt;N = 10&lt;br /&gt;for i in range(N):&lt;br /&gt;    x = random.choice(R)&lt;br /&gt;    y = random.choice(R)    &lt;br /&gt;    xw = word(x)&lt;br /&gt;    print 'x    ', x&lt;br /&gt;    yw = word(y)&lt;br /&gt;    print 'y    ', y&lt;br /&gt;    &lt;br /&gt;    print 'x + y',&lt;br /&gt;    r = xw + yw&lt;br /&gt;    print r&lt;br /&gt;    S = x+y&lt;br /&gt;    assert S == int(str(r).split()[-1])&lt;br /&gt;    print 'check', x, '+', y, '=', S&lt;br /&gt;    &lt;br /&gt;    print 'x * y',&lt;br /&gt;    r = xw * yw&lt;br /&gt;    print r&lt;br /&gt;    P = x*y&lt;br /&gt;    assert P == int(str(r).split()[-1])&lt;br /&gt;    print 'check', x, '*', y, '=', P&lt;br /&gt;    &lt;br /&gt;    for i in range(2,N*2):&lt;br /&gt;        try:&lt;br /&gt;            r = xw**i&lt;br /&gt;        except ValueError:&lt;br /&gt;            i = i-1&lt;br /&gt;            break&lt;br /&gt;    &lt;br /&gt;    z = i&lt;br /&gt;    print 'z     ', z&lt;br /&gt;    print 'x**z ', r&lt;br /&gt;    E = x**z&lt;br /&gt;    try:&lt;br /&gt;        assert E == int(str(r).split()[-1])&lt;br /&gt;    except AssertionError:&lt;br /&gt;        print 'ran into a slight problem\n'&lt;br /&gt;        continue&lt;br /&gt;    print 'check', x,'**', z, '=', E&lt;br /&gt;    print&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7619015056950161625?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7619015056950161625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7619015056950161625' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7619015056950161625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7619015056950161625'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/binary-multiplication-again.html' title='Binary multiplication, again'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3249524835480261589</id><published>2011-08-31T15:04:00.000-04:00</published><updated>2011-08-31T15:04:33.989-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><title type='text'>Dissecting RSA keys in Python (4)</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;Still working with RSA keys.  I accomplished the most important of the items left undone so far, to use the keys to encrypt a message using my own code.&lt;br /&gt;&lt;br /&gt;In the process, I learned a new simple Python fact:  the &lt;code&gt;pow&lt;/code&gt; function (which is now a built-in), can take a modulus as a third argument.  &lt;br /&gt;&lt;br /&gt;And, it works where this doesn't seem to:  (x**y) % z&lt;br /&gt;&lt;br /&gt;(I discovered this by digging into the rsa module source).&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;python -m timeit -s "import rsa;  \&lt;br /&gt;f = open('id_rsa');  data = f.read(); f.close(); k = rsa.PrivateKey.load_pkcs1(data)"\&lt;br /&gt; "41330915578951772302369**k.e % k.n"&lt;br /&gt;&lt;br /&gt;10000 loops, best of 3: 79.4 usec per loop&lt;br /&gt;&lt;br /&gt;python -m timeit -s "import rsa;  \&lt;br /&gt;f = open('id_rsa');  data = f.read(); f.close(); k = rsa.PrivateKey.load_pkcs1(data)"\&lt;br /&gt; "pow(41330915578951772302369, k.e, k.n)"&lt;br /&gt;&lt;br /&gt;10000 loops, best of 3: 70.2 usec per loop&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;In the example here, both work and have about the same timing.  But in the code below, the first version hangs when doing decryption (with a large base).  Here's the output, followed by the script.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; python encode.py &lt;br /&gt;m:   Hello, secret world!&lt;br /&gt;p:   .xyz.Hello, secret world!.xyz.&lt;br /&gt;a:   413309155789517723023698766343791993289928631329&lt;br /&gt;c:   11434905702482726455415220687715293368262190253795 ..&lt;br /&gt;i:   413309155789517723023698766343791993289928631329&lt;br /&gt;r:   Hello, secret world!&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;code&gt;encode.py&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;import rsa&lt;br /&gt;&lt;br /&gt;with open('id_rsa') as f:&lt;br /&gt;    data = f.read()&lt;br /&gt;k = rsa.PrivateKey.load_pkcs1(data)&lt;br /&gt;n = k.n&lt;br /&gt;e = k.e&lt;br /&gt;d = k.d&lt;br /&gt;&lt;br /&gt;def my_atoi(s):&lt;br /&gt;    L = [ord(c) for c in s]&lt;br /&gt;    k = 256&lt;br /&gt;    iL = L[:]&lt;br /&gt;    iL.reverse()&lt;br /&gt;    x = iL[0]&lt;br /&gt;    for i in iL[1:]:&lt;br /&gt;        x += i*k&lt;br /&gt;        k *= 256&lt;br /&gt;    return x&lt;br /&gt;&lt;br /&gt;def my_itoa(i):&lt;br /&gt;    rL = list()&lt;br /&gt;    while i:&lt;br /&gt;        rL.append(i%256)&lt;br /&gt;        i = i/256&lt;br /&gt;    rL.reverse()&lt;br /&gt;    return ''.join([chr(n) for n in rL])&lt;br /&gt;&lt;br /&gt;def encrypt(m):&lt;br /&gt;    return m**e % n&lt;br /&gt;    &lt;br /&gt;def decrypt(c):&lt;br /&gt;    # note:  c**d % n fails&lt;br /&gt;    return pow(c,d,n)&lt;br /&gt;    &lt;br /&gt;if __name__ == '__main__':&lt;br /&gt;    m = 'Hello, secret world!'&lt;br /&gt;    pad = '.xyz.'&lt;br /&gt;    p = pad + m + pad&lt;br /&gt;    a = my_atoi(m)&lt;br /&gt;    c = encrypt(a)&lt;br /&gt;    i = decrypt(c)&lt;br /&gt;    r = my_itoa(i)&lt;br /&gt;    r = r.replace(pad,'')&lt;br /&gt;&lt;br /&gt;    L = zip('mpacir',[m,p,a,c,i,r])&lt;br /&gt;    N = 50&lt;br /&gt;    for varname, var in L:&lt;br /&gt;        s = str(var)&lt;br /&gt;        print varname + ':  ', s[:N],&lt;br /&gt;        if len(s) &gt; N:  print '..'&lt;br /&gt;        else:  print&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3249524835480261589?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3249524835480261589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3249524835480261589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3249524835480261589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3249524835480261589'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python-4.html' title='Dissecting RSA keys in Python (4)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8955960849981295369</id><published>2011-08-31T08:00:00.000-04:00</published><updated>2011-08-31T13:07:58.194-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><category scheme='http://www.blogger.com/atom/ns#' term='binary'/><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><title type='text'>Dissecting RSA keys in Python (3)</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;I'm working on understanding the structure of RSA keys as output by the ssh-keygen utility (previous posts &lt;a href="http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python.html"&gt;here&lt;/a&gt; and &lt;a href="http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python-2.html"&gt;here&lt;/a&gt;).  At the risk of becoming redundant, I want to try to simplify what we did previously.  Let's begin by rehashing &lt;a href="http://telliott99.blogspot.com/2009/11/about-ten-days-ago-i-posted-about.html"&gt;old material&lt;/a&gt; on bytes in Python:&lt;br /&gt;&lt;br /&gt;It's easy to get confused between a byte and its string representation, or for that matter, between an unsigned int and its string representation.  Although hexadecimal is natural too, it's perhaps easiest to think of an individual byte in terms of the decimal equivalent (0..255).  That's because a Python int converts easily to chr, bin, and hex.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; i = 35&lt;br /&gt;&gt;&gt;&gt; c = chr(i)&lt;br /&gt;&gt;&gt;&gt; c&lt;br /&gt;'#'&lt;br /&gt;&gt;&gt;&gt; i == ord(c)&lt;br /&gt;True&lt;br /&gt;&gt;&gt;&gt; b = bin(i)&lt;br /&gt;&gt;&gt;&gt; b&lt;br /&gt;'0b100011'&lt;br /&gt;&gt;&gt;&gt; h = hex(i)&lt;br /&gt;&gt;&gt;&gt; h&lt;br /&gt;'0x23'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Notice that hex and bin both give unpadded output:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; hex(1)&lt;br /&gt;'0x1'&lt;br /&gt;&gt;&gt;&gt; bin(1)&lt;br /&gt;'0b1'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Don't be fooled.  h and b here are 'str' datatypes.  But these string representations of bin and hex values go back to int easily (though we must specify the old base explicitly):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; int(b,2)&lt;br /&gt;35&lt;br /&gt;&gt;&gt;&gt; int(h,16)&lt;br /&gt;35&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;To interconvert hex and bin, it's easiest to go through int:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; bin(35)&lt;br /&gt;'0b100011'&lt;br /&gt;&gt;&gt;&gt; hex(35)&lt;br /&gt;'0x23'&lt;br /&gt;&gt;&gt;&gt; hex(int(bin(35),2))&lt;br /&gt;'0x23'&lt;br /&gt;&gt;&gt;&gt; bin(int(hex(35),16))&lt;br /&gt;'0b100011'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The &lt;a href="http://docs.python.org/library/struct.html#module-struct"&gt;struct module&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;This module performs conversions between Python values and C structs represented as Python strings. This can be used in handling binary data stored in files or from network connections, among other sources. It uses Format Strings as compact descriptions of the layout of the C structs and the intended conversion to/from Python values.&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;unpack&lt;/code&gt; works on the particular string representation of a byte in which it is a single character:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; i = 35&lt;br /&gt;&gt;&gt;&gt; c = chr(i)&lt;br /&gt;&gt;&gt;&gt; c&lt;br /&gt;'#'&lt;br /&gt;&gt;&gt;&gt; unpack('B',c)&lt;br /&gt;(35,)&lt;br /&gt;&gt;&gt;&gt; b = bin(i)&lt;br /&gt;&gt;&gt;&gt; unpack('B',b)&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "&amp;lt;stdin&gt;", line 1, in &amp;lt;module&gt;&lt;br /&gt;struct.error: unpack requires a string argument of length 1&lt;br /&gt;&gt;&gt;&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;To construct a multi-byte value like a 4-byte unsigned int we can do this:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; h = '\x23'&lt;br /&gt;&gt;&gt;&gt; type(h)&lt;br /&gt;&amp;lt;type 'str'&gt;&lt;br /&gt;&gt;&gt;&gt; b_little = '\x23\x00\x00\x00'&lt;br /&gt;&gt;&gt;&gt; type(b_little)&lt;br /&gt;&amp;lt;type 'str'&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;With multi-byte objects (like ints) we get into endian-ness---'I' is the format for an unsigned int, and '&gt;' means big-endian:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; unpack('I', b_little)&lt;br /&gt;(35,)&lt;br /&gt;&gt;&gt;&gt; b_big = '\x00\x00\x00\x23'&lt;br /&gt;&gt;&gt;&gt; unpack('I', b_big)&lt;br /&gt;(587202560,)&lt;br /&gt;&gt;&gt;&gt; unpack('&gt;I', b_big)&lt;br /&gt;(35,)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;One can also use the &lt;a href="http://docs.python.org/library/binascii.html"&gt;binascii&lt;/a&gt; module, but this is more complicated.  Let's write two bytes to a file and then read the binary data:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; fn = 'temp'&lt;br /&gt;&gt;&gt;&gt; FH = open(fn,'w')&lt;br /&gt;&gt;&gt;&gt; FH.write('##')&lt;br /&gt;&gt;&gt;&gt; FH.close()&lt;br /&gt;&gt;&gt;&gt; FH = open(fn,'rb')&lt;br /&gt;&gt;&gt;&gt; data = FH.read()&lt;br /&gt;&gt;&gt;&gt; FH.close()&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This "data" is still a string:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; type(data)&lt;br /&gt;&amp;lt;type 'str'&gt;&lt;br /&gt;&gt;&gt;&gt; data&lt;br /&gt;'##'&lt;br /&gt;&gt;&gt;&gt; len(data)&lt;br /&gt;2&lt;br /&gt;&gt;&gt;&gt; b2a_hex(data[0])&lt;br /&gt;'23'&lt;br /&gt;&gt;&gt;&gt; b2a_hex(data)&lt;br /&gt;'2323'&lt;br /&gt;&gt;&gt;&gt; b2a_hex('#Az')&lt;br /&gt;'23417a'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Or you can get fancy, but it seems unnecessary..&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; import array&lt;br /&gt;&gt;&gt;&gt; L = array.array('B','#Az')&lt;br /&gt;&gt;&gt;&gt; type(L)&lt;br /&gt;&amp;lt;type 'array.array'&gt;&lt;br /&gt;&gt;&gt;&gt; L[0]&lt;br /&gt;35&lt;br /&gt;&gt;&gt;&gt; L[1]&lt;br /&gt;65&lt;br /&gt;&gt;&gt;&gt; L&lt;br /&gt;array('B', [35, 65, 122])&lt;br /&gt;&gt;&gt;&gt; b2a_hex(L)&lt;br /&gt;'23417a'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;With all this in mind, we can redo the script from yesterday to read the base64-encoded key data in a way that is simply understandable.  The output first:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; python read.py &lt;br /&gt;dlen 7&lt;br /&gt;dlen 1&lt;br /&gt;dlen 129&lt;br /&gt;&lt;br /&gt;209,8,39,27 .. 169,97,145,127&lt;br /&gt;0xd1,0x8,0x27,0x1b .. 0xa9,0x61,0x91,0x7f &lt;br /&gt;&lt;br /&gt;1467871546 .. 1722964351&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We decode the data and break it into 3 parts exactly as before.  Looking at the third part, we unpack it byte by byte.  The result of unpacking is a list of ints.  We convert that list directly into the large number n (by doing b * 256**i for each byte, moving along the list in reverse order), or we can convert the ints into hex values, assemble that list into one long hex string, and then call &lt;code&gt;eval&lt;/code&gt; as before.  It seems perfectly transparent now.&lt;br /&gt;&lt;br /&gt;It even seems clear (in retrospect) why there is an additional null byte after the int that specifies the size of the third segment.  It is probably to align the base64 encoding to begin with the first data byte.&lt;br /&gt;&lt;br /&gt;The only remaining difficulty is that this approach fails for the private key.  So that's still a mystery.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;read.py&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;import base64&lt;br /&gt;from struct import unpack&lt;br /&gt;&lt;br /&gt;FH = open('data.txt','r')&lt;br /&gt;data = FH.read()&lt;br /&gt;FH.close()&lt;br /&gt;b64_data = ''.join(data.strip().split())&lt;br /&gt;data = base64.b64decode(b64_data)&lt;br /&gt;&lt;br /&gt;L = list()&lt;br /&gt;while data:&lt;br /&gt;    dlen = unpack('&gt;I',data[:4])[0]&lt;br /&gt;    L.append(data[4:dlen+4])&lt;br /&gt;    data = data[dlen+4:]&lt;br /&gt;    print 'dlen', dlen&lt;br /&gt;print&lt;br /&gt;&lt;br /&gt;# let's look at n&lt;br /&gt;bL = L[2]&lt;br /&gt;bL = bL[1:]    # extra null first, why?&lt;br /&gt;iL = [unpack('B',b)[0] for b in bL]&lt;br /&gt;hL = [hex(i) for i in iL]&lt;br /&gt;&lt;br /&gt;# look at the int and hex values&lt;br /&gt;pL = [str(n) for n in iL]&lt;br /&gt;print ','.join(pL[:4]), '..', ','.join(pL[-4:])&lt;br /&gt;print ','.join(hL[:4]), '..',&lt;br /&gt;print ','.join(hL[-4:]), '\n'&lt;br /&gt;&lt;br /&gt;# first just do the computation ourselves&lt;br /&gt;m = 256&lt;br /&gt;iL.reverse()&lt;br /&gt;n = iL[0]&lt;br /&gt;for i in iL[1:]:&lt;br /&gt;    n += i*m&lt;br /&gt;    m *= 256&lt;br /&gt;    &lt;br /&gt;s = str(n)&lt;br /&gt;print s[:10], '..', s[-10:]&lt;br /&gt;    &lt;br /&gt;# hex doesn't pad the output&lt;br /&gt;# remove the '0x' and add the extra '0' if needed&lt;br /&gt;for i in range(len(hL)):&lt;br /&gt;    b = hL[i]&lt;br /&gt;    if len(b) &lt; 4:&lt;br /&gt;        hL[i] = '0' + b[-1]&lt;br /&gt;    else:&lt;br /&gt;        hL[i] = b[-2:]  &lt;br /&gt;h = '0x' + ''.join(hL)&lt;br /&gt;nh = eval(h)&lt;br /&gt;assert n == nh&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8955960849981295369?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8955960849981295369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8955960849981295369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8955960849981295369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8955960849981295369'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python-3.html' title='Dissecting RSA keys in Python (3)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-9011507717260095415</id><published>2011-08-30T18:09:00.003-04:00</published><updated>2011-08-31T08:42:06.261-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><title type='text'>Dissecting RSA keys in Python (2)</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;The public key from last time was given (in &lt;code&gt;id_rsa.pub&lt;/code&gt;) as:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;AAAAB3NzaC1yc2EAAAABIwAAAIEA0QgnG+LBQosx&lt;br /&gt;pbkJIU0eWV9Zf7L63fy3BXp6T9RQH84yISs8SMvF&lt;br /&gt;V4J1NYJQtNpGopNFlvzsuFnnxaRaM8ureFIQVa8k&lt;br /&gt;/dRzv3r7QyIuoGyNQLDk3K8Tse/55fjuIxJFEf5j&lt;br /&gt;voJs3Z/jYdPHreg8wzNCB/uMkbCccYsVt6lhkX8=&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;(It has been broken into 40 character lines).  If we look at the first 32 characters of this base64 encoding:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;AAAAB3NzaC1yc2EA&lt;br /&gt;AAABIwAAAIEA0Qgn&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;the decoded version of this in hex is:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;0x0  0x0  0x0 0x7  0x73 0x73 0x68 0x2d 0x72 0x73 0x61 0x0&lt;br /&gt;0x0  0x0  0x1 0x23 0x0  0x0  0x0  0x81 0x0  0xd1 0x8  0x27&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The first four bytes are&lt;br /&gt;&lt;br /&gt;&lt;code&gt;0x0  0x0  0x0 0x7&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;interpreted as a 32-bit unsigned int that is equal to 7, and indicates that the next 7 bytes are grouped together to form this element of the data (which is 'rsa-ssh', as I mentioned &lt;a href="http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python.html"&gt;before&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;0x73 0x73 0x68 0x2d 0x72 0x73 0x61&lt;br /&gt;   s    s    h    -    r    s    a&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The next 4 bytes after that are:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;0x0  0x0  0x0 0x1&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;indicating the following block is a single byte of data:  &lt;code&gt;0x23&lt;/code&gt;.  In ASCII-encoding this would be the character '#', but it's actually an unsigned int:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; int('0x00000023', 16)&lt;br /&gt;35&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This is the value of the exponent for the key pair.  More on this in a moment.  Finally we get to &lt;br /&gt;&lt;br /&gt;&lt;code&gt;0x0  0x0  0x0  0x81&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; int('0x00000081', 16)&lt;br /&gt;129&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;It turns out there are exactly 129 bytes left in the data.  In the code from the first post (from here), we used the struct module to unpack these three segments of data (we labeled them "parts").  &lt;br /&gt;&lt;br /&gt;According to the &lt;a href="http://docs.python.org/library/struct.html"&gt;docs&lt;/a&gt;, the struct module can be used to interpret strings as packed binary data.&lt;br /&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;The first argument to unpack is a &lt;a href="http://docs.python.org/library/struct.html#format-strings"&gt;format string&lt;/a&gt;.  The first character of the format string can be used to indicate the byte order, size and alignment of the packed data&lt;br /&gt;&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;The '&gt;' indicates big-endian data, data laid out in registers in the same order as it is in memory.  While Intel x86 (and current Macs) are little-endian, network order is big-endian and (I suppose) the SSH standard respects this.  The next format character 'I' indicates the data following are unsigned ints.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;import struct&lt;br /&gt;&lt;br /&gt;hL = ['0x0','0x0','0x0','0x81']&lt;br /&gt;iL = [int(h,16) for h in hL]&lt;br /&gt;cdata = ''.join([chr(n) for n in iL])&lt;br /&gt;res = struct.unpack('&gt;I', cdata)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; print res&lt;br /&gt;(129,)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;It returns a tuple and we want the first value.&lt;br /&gt;&lt;br /&gt;In the code from yesterday, we simply copied the correct number of bytes in each segment (as "characters"---not ASCII).  &lt;br /&gt;&lt;br /&gt;In the last part of this example, we need to transform those bytes into numerical data.  We'll use struct.unpack again, except this time specifying binary data.  For the exponent we had a single byte '\x23'', corresponding to character '#' which is 35 as an unsigned int:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; struct.unpack('B','#')&lt;br /&gt;(35,)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Our function f passed the first element of this tuple back to a big list comprehension.  &lt;br /&gt;&lt;br /&gt;&lt;code&gt;e = eval('0x' + ''.join(['%02X' % f(x) for x in parts[1]]))&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In the case of the exponent (e) it operated on only a single value, so I'll rewrite it to clarify what this does.  Remembering that f(x) will return 35, we'll get rid of the list stuff and just do:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; s = '%02X' % 35&lt;br /&gt;&gt;&gt;&gt; s&lt;br /&gt;'23'&lt;br /&gt;&gt;&gt;&gt; e = eval('0x' + s)&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; e&lt;br /&gt;35&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;(I'm not too swift with format strings, but you can read about them &lt;a href="http://docs.python.org/library/stdtypes.html#string-formatting-operations"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;And it doesn't do much in this case!  But suppose we had two of these bytes in a row.  Then:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; s = ('%02X' % 35) * 2&lt;br /&gt;&gt;&gt;&gt; s&lt;br /&gt;'2323'&lt;br /&gt;&gt;&gt;&gt; eval('0x' + s)&lt;br /&gt;8995&lt;br /&gt;&gt;&gt;&gt; 35*256 + 35&lt;br /&gt;8995&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;code&gt;eval&lt;/code&gt; will turn our string of bytes into a multi-byte unsigned int.  This is news to me.  So, if we actually had the string of bytes in hex divided into two sets of bytes, those up to and including '0x81'&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;['0x0', '0x0', '0x0', '0x7', '0x73', '0x73', '0x68', '0x2d', '0x72', '0x73', '0x61', '0x0', '0x0', '0x0', '0x1', '0x23', '0x0', '0x0', '0x0', '0x81']&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and those after:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;L = ['0x0', '0xd1', '0x8', '0x27', '0x1b', '0xe2', &lt;br /&gt;      '0xc1', '0x42', '0x8b', '0x31', '0xa5', '0xb9', '0x9', '0x21', '0x4d', '0x1e', '0x59', &lt;br /&gt;      '0x5f', '0x59', '0x7f', '0xb2', '0xfa', '0xdd', '0xfc', '0xb7', '0x5', '0x7a', '0x7a', &lt;br /&gt;      '0x4f', '0xd4', '0x50', '0x1f', '0xce', '0x32', '0x21', '0x2b', '0x3c', '0x48', '0xcb', &lt;br /&gt;      '0xc5', '0x57', '0x82', '0x75', '0x35', '0x82', '0x50', '0xb4', '0xda', '0x46', '0xa2', &lt;br /&gt;      '0x93', '0x45', '0x96', '0xfc', '0xec', '0xb8', '0x59', '0xe7', '0xc5', '0xa4', '0x5a', &lt;br /&gt;      '0x33', '0xcb', '0xab', '0x78', '0x52', '0x10', '0x55', '0xaf', '0x24', '0xfd', '0xd4', &lt;br /&gt;      '0x73', '0xbf', '0x7a', '0xfb', '0x43', '0x22', '0x2e', '0xa0', '0x6c', '0x8d', '0x40', &lt;br /&gt;      '0xb0', '0xe4', '0xdc', '0xaf', '0x13', '0xb1', '0xef', '0xf9', '0xe5', '0xf8', '0xee', &lt;br /&gt;      '0x23', '0x12', '0x45', '0x11', '0xfe', '0x63', '0xbe', '0x82', '0x6c', '0xdd', '0x9f', &lt;br /&gt;      '0xe3', '0x61', '0xd3', '0xc7', '0xad', '0xe8', '0x3c', '0xc3', '0x33', '0x42', '0x7', &lt;br /&gt;      '0xfb', '0x8c', '0x91', '0xb0', '0x9c', '0x71', '0x8b', '0x15', '0xb7', '0xa9', '0x61', &lt;br /&gt;      '0x91', '0x7f', '0x0']&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Note:  The extra byte at the end here is caused by our having decoded by hand.&lt;br /&gt;&lt;br /&gt;Paste it into the interpreter.  Then, they have to be padded out...&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;for i in range(len(L)):&lt;br /&gt;    s = L[i]&lt;br /&gt;    c = s[-1]&lt;br /&gt;    if len(s) &lt; 4:  &lt;br /&gt;         L[i] = '0' + c&lt;br /&gt;    else:  &lt;br /&gt;        L[i] = s[-2:]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;Remove the first and last bytes and turn it into one long hex value:&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; s = '0x' + ''.join(L[1:-1])&lt;br /&gt;&gt;&gt;&gt; eval(s)&lt;br /&gt;146787154640181728129549360865206451974125178122992752499327844555082827713683060312609720092642289502088305950292885968241446393671268243539585900329449529436170858131743078225065287541399805133121852823856839448386268013284889428740476278604926908637093742329548018673369795976229837442944484597101722964351L&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;That matches what we got &lt;a href="http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python.html"&gt;yesterday&lt;/a&gt;, and what the rsa module gave us for n from the private key.&lt;br /&gt;&lt;br /&gt;This use of &lt;code&gt;eval&lt;/code&gt; seems to be widely &lt;a href="http://stackoverflow.com/questions/5281799/how-would-one-convert-a-python-string-representation-of-a-byte-string-to-an-actua"&gt;known&lt;/a&gt;, but I would never have appreciated it from just reading the &lt;a href="http://docs.python.org/library/functions.html#eval"&gt;docs&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here is a quick script that shows all the values for each set of four characters in the base64 encoding, first 9 bytes of output first:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; python script2.py &lt;br /&gt;['A', 'A', 'A', 'A']&lt;br /&gt;[0, 0, 0, 0]&lt;br /&gt;['0b0', '0b0', '0b0', '0b0']&lt;br /&gt;['000000', '000000', '000000', '000000']&lt;br /&gt;['00000000', '00000000', '00000000']&lt;br /&gt;0x0 0x0 0x0&lt;br /&gt;0 0 0 &lt;br /&gt;&lt;br /&gt;['B', '3', 'N', 'z']&lt;br /&gt;[1, 55, 13, 51]&lt;br /&gt;['0b1', '0b110111', '0b1101', '0b110011']&lt;br /&gt;['000001', '110111', '001101', '110011']&lt;br /&gt;['00000111', '01110011', '01110011']&lt;br /&gt;0x7 0x73 0x73&lt;br /&gt;7 115 115 &lt;br /&gt;&lt;br /&gt;['a', 'C', '1', 'y']&lt;br /&gt;[26, 2, 53, 50]&lt;br /&gt;['0b11010', '0b10', '0b110101', '0b110010']&lt;br /&gt;['011010', '000010', '110101', '110010']&lt;br /&gt;['01101000', '00101101', '01110010']&lt;br /&gt;0x68 0x2d 0x72&lt;br /&gt;104 45 114&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;from string import *&lt;br /&gt;v = True&lt;br /&gt;&lt;br /&gt;cL = list(uppercase + lowercase + digits + '+/')&lt;br /&gt;D = dict(zip(cL,range(len(cL))))&lt;br /&gt;D['='] = 0&lt;br /&gt;&lt;br /&gt;key = '''AAAAB3NzaC1yc2EAAAABIwAAAIEA0QgnG+LBQosxpbkJIU0eWV9Zf7L63fy3BXp6T9RQH84yISs8SMvFV4J1NYJQtNpGopNFlvzsuFnnxaRaM8ureFIQVa8k/dRzv3r7QyIuoGyNQLDk3K8Tse/55fjuIxJFEf5jvoJs3Z/jYdPHreg8wzNCB/uMkbCccYsVt6lhkX8='''&lt;br /&gt;&lt;br /&gt;L = list(key)&lt;br /&gt;&lt;br /&gt;while L:&lt;br /&gt;    s = L[:4]&lt;br /&gt;    L = L[4:]&lt;br /&gt;    if v:  print s&lt;br /&gt;    dL = [D[c] for c in s]&lt;br /&gt;    if v:  print dL&lt;br /&gt;    dL = [bin(c) for c in dL]&lt;br /&gt;    if v:  print dL&lt;br /&gt;    bL = list()&lt;br /&gt;    for b in dL:&lt;br /&gt;        n = 8 - len(b)&lt;br /&gt;        b = n*'0' + b[2:]&lt;br /&gt;        bL.append(b)&lt;br /&gt;    if v:  print bL&lt;br /&gt;    b = ''.join(bL)&lt;br /&gt;    bL = [b[:8], b[8:16], b[16:]]&lt;br /&gt;    if v:  print bL&lt;br /&gt;    iL = [int('0b' + b,2) for b in bL]&lt;br /&gt;    for i in iL:&lt;br /&gt;        print hex(i),&lt;br /&gt;    print&lt;br /&gt;    for i in iL:&lt;br /&gt;        print i,&lt;br /&gt;    print '\n'&lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-9011507717260095415?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/9011507717260095415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=9011507717260095415' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/9011507717260095415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/9011507717260095415'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python-2.html' title='Dissecting RSA keys in Python (2)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3122345202310925662</id><published>2011-08-29T20:25:00.001-04:00</published><updated>2011-08-31T11:18:16.966-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><title type='text'>Dissecting RSA keys in Python</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;I want to look at RSA keys a little bit more in this post.  Let's generate a public/private pair (1024 bits) using the SSH utility keygen (no passphrase):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; ssh-keygen -b 1024 -t rsa &lt;br /&gt;Generating public/private rsa key pair.&lt;br /&gt;Enter file in which to save the key (/Users/telliott_admin/.ssh/id_rsa): id_rsa&lt;br /&gt;Enter passphrase (empty for no passphrase): &lt;br /&gt;Enter same passphrase again: &lt;br /&gt;Your identification has been saved in id_rsa.&lt;br /&gt;Your public key has been saved in id_rsa.pub.&lt;br /&gt;The key fingerprint is:&lt;br /&gt;96:49:5d:40:b1:90:de:99:c5:05:43:f2:92:45:69:67 telliott_admin@c-98-236-78-154.hsd1.wv.comcast.net&lt;br /&gt;The key's randomart image is:&lt;br /&gt;+--[ RSA 1024]----+&lt;br /&gt;|        .o=*B+.  |&lt;br /&gt;|        .o B=.E  |&lt;br /&gt;|       ...==.o   |&lt;br /&gt;|       ..o+.     |&lt;br /&gt;|        S        |&lt;br /&gt;|       .         |&lt;br /&gt;|                 |&lt;br /&gt;|                 |&lt;br /&gt;|                 |&lt;br /&gt;+-----------------+&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;[ To be honest, at this point, I'm not actually sure this is the randomart that goes with the example in this post.. but I think it could be  :) ]&lt;br /&gt;&lt;br /&gt;Start with the "public" key.  The data in the file looks like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;id_rsa.pub&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA0QgnG+LBQosxpbkJIU0eWV9Zf7L63fy3BXp6T9RQH84yISs8SMvFV4J1NYJQtNpGopNFlvzsuFnnxaRaM8ureFIQVa8k/dRzv3r7QyIuoGyNQLDk3K8Tse/55fjuIxJFEf5jvoJs3Z/jYdPHreg8wzNCB/uMkbCccYsVt6lhkX8= my_identifier&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Where my_identifier is&lt;br /&gt;&lt;br /&gt;&lt;code&gt;telliott_admin@c-myipaddress_with_dashes.hsd1.wv.comcast.net&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The common representation of RSA keys (like we see in the file above) uses &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;base64&lt;/a&gt; format.  I was confused about this at first, but found a great explanation &lt;a href="http://www.doughellmann.com/PyMOTW/base64/"&gt;here&lt;/a&gt;, and of course in wikipedia:&lt;br /&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;The base64, base32, and base16 encodings convert 8 bit bytes to values with 6, 5, or 4 bits of useful data per byte, allowing non-ASCII bytes to be encoded as ASCII characters for transmission over protocols that require plain ASCII, such as SMTP. The base values correspond to the length of the alphabet used in each encoding. There are also URL-safe variations of the original encodings that use slightly different results.&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Consider the byte &lt;code&gt;1001-1110&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;We can encode this byte using hexadecimal representation as &lt;code&gt;'9e'&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; b = 0b10011110&lt;br /&gt;&gt;&gt;&gt; b&lt;br /&gt;158&lt;br /&gt;&gt;&gt;&gt; hex(b)&lt;br /&gt;'0x9e'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I didn't actually know you could do this, i.e. using 0b with no quotes (see &lt;a href="http://stackoverflow.com/questions/1476/how-do-you-express-binary-literals-in-python"&gt;SO&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;The encoding of those 8 bits (one byte) as ASCII characters takes 2 bytes.  The '9' and the 'e' take up that much space.  An advantage of this representation of the byte is that it's easy to read, also the information can be transmitted to devices that are expecting an ASCII string, where the highest-value bit should be unset.  &lt;br /&gt;&lt;br /&gt;A disadvantage is that it doubles the size of the string that we're transmitting.  As the quote indicates, the other encodings cram more bits of information into the byte to be transmitted.  In &lt;a href="http://en.wikipedia.org/wiki/Base32"&gt;base32&lt;/a&gt; we could use (&lt;a href="http://tools.ietf.org/html/rfc4648"&gt;RFC4648&lt;/a&gt;) the characters 'A'..'Z' plus '2'..'7'.&lt;br /&gt;&lt;br /&gt;In base64 we use uppercase, lowercase, digits plus '+' and '/', except &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;that&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;Using standard Base64 in URL requires encoding of '+', '/' and '=' characters into special percent-encoded hexadecimal sequences ('+' = '%2B', '/' = '%2F' and '=' = '%3D'), which makes the string unnecessarily longer.&lt;br /&gt;For this reason, a modified Base64 for URL variant exists, where no padding '=' will be used, and the '+' and '/' characters of standard Base64 are respectively replaced by '-' and '_',&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;The wikipedia article has a great graphic showing an encoding in detail.  We do conversions easily by using the Python base64 module.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-I9jxkjrkTLU/Tlwrlr7qutI/AAAAAAAABxc/Vee_P943_D0/s1600/Screen%2Bshot%2B2011-08-29%2Bat%2B4.59.39%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="110" width="320" src="http://3.bp.blogspot.com/-I9jxkjrkTLU/Tlwrlr7qutI/AAAAAAAABxc/Vee_P943_D0/s320/Screen%2Bshot%2B2011-08-29%2Bat%2B4.59.39%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; import base64&lt;br /&gt;&gt;&gt;&gt; e = base64.b64encode&lt;br /&gt;&gt;&gt;&gt; d = base64.b64decode&lt;br /&gt;&gt;&gt;&gt; e('Man')&lt;br /&gt;'TWFu'&lt;br /&gt;&gt;&gt;&gt; d('TWFu')&lt;br /&gt;'Man'&lt;br /&gt;&gt;&gt;&gt; s = 'Fourscore, and seven years ago'&lt;br /&gt;&gt;&gt;&gt; len(s)&lt;br /&gt;30&lt;br /&gt;&gt;&gt;&gt; c = e(s)&lt;br /&gt;&gt;&gt;&gt; c&lt;br /&gt;'Rm91cnNjb3JlLCBhbmQgc2V2ZW4geWVhcnMgYWdv'&lt;br /&gt;&gt;&gt;&gt; d(c)&lt;br /&gt;'Fourscore, and seven years ago'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;The encoding process looks at each sequence of 24 bits in the input (3 bytes) and encodes those same 24 bits spread over 4 bytes in the output. The last two characters [in the next example], the ==, are padding because the number of bits in the original string was not evenly divisible by 24 in this example.&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt;&gt;&gt; e('Ma')&lt;br /&gt;'TWE='&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We break this two byte (16 bit) value up into 6 + 6 + 6 = 18 bits---that makes three base64 values, and the third one is now E rather than F because the bit pattern is 000100, where the last two 00 are padding.  Additional adding is added to bring us back to the byte boundary.&lt;br /&gt;&lt;br /&gt;In Lincoln's famous phrase, there are 30 bytes, which is evenly divisible by 6, hence no padding is needed.&lt;br /&gt;&lt;br /&gt;The second part of the problem was &lt;a href="http://blog.oddbit.com/2011/05/converting-openssh-public-keys.html"&gt;solved&lt;/a&gt; by a question I found on &lt;a href="http://stackoverflow.com/questions/3299003/how-to-convert-openssh-public-key-file-format-to-pem"&gt;SO&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is my version of the code:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;import base64&lt;br /&gt;import struct&lt;br /&gt;&lt;br /&gt;data = open('id_rsa.pub').read().split(None)[1]&lt;br /&gt;print data[:24]&lt;br /&gt;keydata = base64.b64decode(data)&lt;br /&gt;print keydata[:18]&lt;br /&gt;&lt;br /&gt;parts = []&lt;br /&gt;while keydata:&lt;br /&gt;    dlen = struct.unpack('&gt;I',keydata[:4])[0]&lt;br /&gt;    data, keydata = keydata[4:dlen+4], keydata[4+dlen:]&lt;br /&gt;    parts.append(data)&lt;br /&gt;&lt;br /&gt;def f(x):&lt;br /&gt;    return struct.unpack('B', x)[0]&lt;br /&gt;    &lt;br /&gt;e = eval('0x' + ''.join(['%02X' % f(x) for x in parts[1]]))&lt;br /&gt;print 'e', e&lt;br /&gt;&lt;br /&gt;n = eval('0x' + ''.join(['%02X' % f(x) for x in parts[2]]))&lt;br /&gt;print 'n', n&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I have to confess I haven't sorted this out completely yet.  Nevertheless, it allows us to convert the RSA public key from ssh-keygen to an integer:&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; python script.py&lt;br /&gt;AAAAB3NzaC1yc2EAAAABIwAA&lt;br /&gt;ssh-rsa#&lt;br /&gt;e 35&lt;br /&gt;n 146787154640181728129549360865206451974125178122992752499327844555082827713683060312609720092642289502088305950292885968241446393671268243539585900329449529436170858131743078225065287541399805133121852823856839448386268013284889428740476278604926908637093742329548018673369795976229837442944484597101722964351&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I want to finish by showing that these values are actually correct, and tie the whole thing back to an earlier &lt;a href="http://telliott99.blogspot.com/2011/02/secure-communications-2.html"&gt;discussion&lt;/a&gt; of the mathematics of public key cryptography.&lt;br /&gt;&lt;br /&gt;I found a &lt;a href="http://stuvel.eu/rsa"&gt;module&lt;/a&gt; for Python that handles RSA cryptography.&lt;br /&gt;&lt;br /&gt;One very nice thing about it is that it's pure Python.  It might not be fast, but there's nothing to do to build it.  (I used easy_install).  It turns out that the rsa module can read the private RSA key that we got earlier (top of the post), but not the public key (which is why I learned everything that's come before this point):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; python&lt;br /&gt;Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) &lt;br /&gt;[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; import rsa&lt;br /&gt;&gt;&gt;&gt; with open('id_rsa') as f:  data = f.read()&lt;br /&gt;... &lt;br /&gt;&gt;&gt;&gt; data.split()[4][:50]&lt;br /&gt;'MIICWgIBAAKBgQDRCCcb4sFCizGluQkhTR5ZX1l/svrd/LcFen'&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&gt;&gt;&gt; k = rsa.PrivateKey.load_pkcs1(data)&lt;br /&gt;&gt;&gt;&gt; k.n&lt;br /&gt;146787154640181728129549360865206451974125178122992752499327844555082827713683060312609720092642289502088305950292885968241446393671268243539585900329449529436170858131743078225065287541399805133121852823856839448386268013284889428740476278604926908637093742329548018673369795976229837442944484597101722964351L&lt;br /&gt;&gt;&gt;&gt; k.e&lt;br /&gt;35&lt;br /&gt;&gt;&gt;&gt; k.d&lt;br /&gt;71296617968088267948638260991671705244575086516882194071102095926754516318074629294696149759283397758157177175856544613145845391211758861147798865874304045384903321200809536161346504709634159813307741235395231601606901597492591281205810328850837168587984349087962868939575631849929827946396907884195208774355L&lt;br /&gt;&gt;&gt;&gt; k.p&lt;br /&gt;12214944519618901215070692893221534580187337690484280451921546594832793966376942655508370083135703324858458340368238021755353370324360760471666368429071147L&lt;br /&gt;&gt;&gt;&gt; k.q&lt;br /&gt;12017013618393528112233953119917677248859562342149056793052943111068006176296374093622600767249370271694572460567324457033873003984957249202580919628769533L&lt;br /&gt;&gt;&gt;&gt; k.n == k.p * k.q&lt;br /&gt;True&lt;br /&gt;&gt;&gt;&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;You can see that n equals p * q and that it matches what we eventually obtained from the public key file (&lt;code&gt;id_rsa.pub&lt;/code&gt;) above.  That's pretty cool.&lt;br /&gt;&lt;br /&gt;Still to do:  use the keys to do encryption and decryption and check that the math is right.  Figure out how the hash/digest is done.  And figure out how the passphrase is used to modify the private key file.  We can even &lt;a href="http://www.cyberciti.biz/faq/howto-ssh-changing-passphrase/"&gt;add a passphrase&lt;/a&gt; at this point to the old version:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ssh-keygen -f id_rsa -p&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I used 'abcde' as a passphrase (weak!):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&gt; cat id_rsa&lt;br /&gt;-----BEGIN RSA PRIVATE KEY-----&lt;br /&gt;Proc-Type: 4,ENCRYPTED&lt;br /&gt;DEK-Info: AES-128-CBC,FB4D3BD371510C4B37552EF6E949CC48&lt;br /&gt;&lt;br /&gt;E+KtbKVAwE4Dxj3vKYgfHpbgqF9Nk6O4vJ+C6wogXEHXr8vkM9SF5pz6lKNfGRbC&lt;br /&gt;S93/lurvq+1+rCuldDNmEjdy36cbgrWJ1CIwB6fq5VyT3+v+AxDMqV9nQkvHjnxR&lt;br /&gt;/ON2n+CjOSklnvmaBk3l8+IvCIKar2hGS/1qHqJRKJ3B1fgd5I8i9yH6hx8yl8Qm&lt;br /&gt;AfVPgBJ4+91dCW2Y8odtXENgjstGtWZkYd0O+EqPuSuPHLu+J7M2KSQNe8aKOhGf&lt;br /&gt;DXCEwR4aGW8EXfRNQpULbi5JruYebYlg3JILm2MaFwy+OW39q1VElvBc5wD01awW&lt;br /&gt;BF7Y9x++bi9krX/G49NzkLdSVshkDMSP+eRZ4sncWvDCrkN2xlWqnNfQ06I+XCVW&lt;br /&gt;FMUmyMFI87eNmjcZOgIi1S+fQtWcbl4o9Hx1z6xcMd7WxOnfIxe5zHIu8C24WONW&lt;br /&gt;spcVxSsHAA57jYa8j292prtK6HDDa6UOAa32hBz1lvC8fMWPxwluTJ8eyeeK/7O6&lt;br /&gt;hNI5G9gM4MsMEMau8O49fEm0RuiT/aB8IXZeEVQNbV/FdixyBBhY53DMnFQ5wau8&lt;br /&gt;OJCpL51S5lj2o8eAJc61SHwX/Fc9uF+rmAFy08tthLuCF2wGdZWsE7IJ8NQzFJA+&lt;br /&gt;Us2dTCjY57V/QoCC41rWh+YP+srcEK1Wp7DfvXcq98N1/+tECyCe/aDdPCIM/8QD&lt;br /&gt;glKrx8Ah7Tsx6of3vCHiYG0q8Yu68NNJOiWrnGMEmP0Gq9yhLYqKrc8a3oIP0Lst&lt;br /&gt;Ss+0p989df73GdM3nyqtLUwAzaCJQnDivLFT6gltEnM=&lt;br /&gt;-----END RSA PRIVATE KEY-----&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3122345202310925662?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3122345202310925662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3122345202310925662' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3122345202310925662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3122345202310925662'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/dissecting-rsa-keys-in-python.html' title='Dissecting RSA keys in Python'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-I9jxkjrkTLU/Tlwrlr7qutI/AAAAAAAABxc/Vee_P943_D0/s72-c/Screen%2Bshot%2B2011-08-29%2Bat%2B4.59.39%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-6648482215417642149</id><published>2011-08-28T16:57:00.000-04:00</published><updated>2011-08-28T16:57:48.942-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='duly quoted'/><title type='text'>Duly quoted</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;Recycled from an earlier &lt;a href="http://telliott99.blogspot.com/2008/05/fun-with-sudoku_9172.html"&gt;post&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;Programs must be written for people to read, and only incidentally for machines to execute.&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;- Abelson &amp; Sussman, SICP&lt;br /&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;How do we convince people that in programming simplicity and clarity—in short: what mathematicians call "elegance"— are not a dispensable luxury, but a crucial matter that decides between success and failure?&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;- E. W. Dijkstra&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-6648482215417642149?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/6648482215417642149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=6648482215417642149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6648482215417642149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6648482215417642149'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/duly-quoted.html' title='Duly quoted'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7929059171148608295</id><published>2011-08-28T16:07:00.004-04:00</published><updated>2011-08-29T20:26:17.216-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><title type='text'>Linux Server SSH</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;To continue with my Ubuntu Linux server &lt;a href="http://telliott99.blogspot.com/2011/08/linux-server.html"&gt;odyssey&lt;/a&gt;, I got SSH working this afternoon for access from my LAN.  As always, heed the &lt;a href="http://telliott99.blogspot.com/search/label/ssh"&gt;warnings&lt;/a&gt;, these posts are without a warranty of any kind, not least because I am a total amateur.  They exist because it's easy to have Google to "&lt;a href="http://www.friday.com/bbum/2009/11/19/california-rice-oil/"&gt;index my brain&lt;/a&gt;" or rather, what was in my brain at a certain time.&lt;br /&gt;&lt;br /&gt;The objective is to enable remote login for my Ubuntu machine running with a local ip address of 10.0.1.2.  We begin by setting a stronger &lt;a href="http://www.thegeekstuff.com/2009/12/how-to-change-password-on-ubuntu/"&gt;password&lt;/a&gt; for my account on Ubuntu under:  System &amp;gt; Preferences &amp;gt; About Me (weirdly, it's not under Passwords and Encryption Keys ..).&lt;br /&gt;&lt;br /&gt;On the client (OS X Snow Leopard Server), I already have some key pairs from a previous test&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&amp;gt; ls ~/.ssh&lt;br /&gt;authorized_keys	id_dsa		id_dsa.pub	known_hosts&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;&lt;br /&gt;but they are DSA keys, which the &lt;a href="https://help.ubuntu.com/10.10/serverguide/C/openssh-server.html"&gt;notes&lt;/a&gt; I'm going to follow deprecate.  We'll make a short 1024 &lt;del&gt;byte&lt;/del&gt; bit RSA pair for now:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;ssh-keygen -b 1024 -t rsa&lt;br /&gt;&lt;br /&gt;&amp;gt; cat id_rsa.pub &lt;br /&gt;ssh-rsa AAAAB..5Eoec= telliott_@c-98-___-__-154.hsd1.wv.comcast.net&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Not sure what the pseudo ip address or "comcast" thing is about.&lt;br /&gt;&lt;br /&gt;I also take this opportunity to set a passphrase for the public key (and of course I make a &lt;a href="http://telliott99.blogspot.com/2010/11/threat-level-yellow.html"&gt;note&lt;/a&gt; of it).  This will be useful (it says) because we can set up the server to require both a password to gain access to the public key, as well as the corresponding private key before login is allowed.&lt;br /&gt;&lt;br /&gt;[UPDATE:  I'm still working my way through this, but I suspect that the previous statement isn't correct.  The passphrase is used to protect the value of the &lt;i&gt;private&lt;/i&gt; key.  So, in this setup OS X will decrypt the private key using the passphrase, and the stored value of the private key in &lt;code&gt;id_rsa&lt;/code&gt; is encrypted.  I'll try to figure all this out soon. ]&lt;br /&gt;&lt;br /&gt;The easiest way to get my new public key onto the server is to use SSH (with password, before we disable it).  The next question is, do we need to install an SSH server?  It appears yes.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;sudo apt-get install openssh-server&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;There is a pre-existing config file &lt;code&gt;/etc/ssh/ssh_config&lt;/code&gt; but after the previous command there are more including &lt;code&gt;sshd_config&lt;/code&gt;.  I make sure to save a copy of this file before I modify it.  Now try:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;ssh te@10.0.1.2&lt;br /&gt;&lt;br /&gt;ssh: connect to host 10.0.1.2 port 22: Connection refused&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;OK, so we need to modify &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;.  &lt;code&gt;Port22&lt;/code&gt; is already uncommented.  Now uncomment:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;PermitRootLogin no&lt;br /&gt;ChallengeResponseAuthentication yes&lt;br /&gt;PasswordAuthentication yes   # we'll set it to no eventually&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;On the server:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;sudo /etc/init.d/ssh restart&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;On the client:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&amp;gt; ssh te@10.0.1.2&lt;br /&gt;The authenticity of host '10.0.1.2 (10.0.1.2)' can't be established.&lt;br /&gt;RSA key fingerprint is d1: .. :83.&lt;br /&gt;Are you sure you want to continue connecting (yes/no)? &lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Check the fingerprint on the the server:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub&lt;br /&gt;&lt;br /&gt;2048 d1: .. :83 /etc/ssh/ssh_host_rsa_key.pub (RSA)&lt;br /&gt;&lt;br /&gt;Are you sure you want to continue connecting (yes/no)? yes&lt;br /&gt;Warning: Permanently added '10.0.1.2' (RSA) to the list of known hosts.&lt;br /&gt;Connection closed by 10.0.1.2&lt;br /&gt;&lt;br /&gt;&amp;gt; ssh te@10.0.1.2&lt;br /&gt;te@10.0.1.2's password: &lt;br /&gt;Welcome to Ubuntu 11.04 (GNU/Linux 2.6.38-11-generic x86_64)&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Now to change to not using our password.  We need to copy our RSA public key to the server in some secure way.  According to the sshd_config file, the "authorized keys file" is &lt;br /&gt;%h/.ssh/authorized_keys.  That's in my home directory.  I do:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;&amp;gt; scp ~/.ssh/id_rsa.pub te@10.0.1.2:~/.ssh/authorized_keys&lt;br /&gt;te@10.0.1.2's password: &lt;br /&gt;id_rsa.pub                                    100%  260     0.3KB/s   00:00    &lt;br /&gt;&lt;br /&gt;te@VB:~$ logout&lt;br /&gt;Connection to 10.0.1.2 closed.&lt;br /&gt;&lt;br /&gt;&amp;gt; ssh te@10.0.1.2&lt;br /&gt;Identity added: /Users/telliott_admin/.ssh/id_rsa (/Users/telliott_admin/.ssh/id_rsa)&lt;br /&gt;Welcome to Ubuntu 11.04 (GNU/Linux 2.6.38-11-generic x86_64)&lt;br /&gt;&lt;br /&gt;* Documentation:  https://help.ubuntu.com/&lt;br /&gt;&lt;br /&gt;Last login: Sun Aug 28 14:35:49 2011 from osxserver.local&lt;br /&gt;te@VB:~$ &lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Now, finally, be sure to turn off password authentication for the ssh server:  &lt;code&gt;PasswordAuthentication no&lt;/code&gt;.  At first, I'm not being prompted for a password to retrieve my public key on the server..  just getting automatically logged in by:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;ssh te@10.0.1.2&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I forgot to do:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll;"&gt;&lt;table bgcolor="#ffffb0" border="0" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style="font-family: monaco;"&gt;ChallengeResponsePasswords yes&lt;br /&gt;&lt;br /&gt;sudo /etc/init.d/ssh restart&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Restart and I get the challenge..  Although it is apparently cached sometimes.  Looks like it works.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7929059171148608295?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7929059171148608295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7929059171148608295' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7929059171148608295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7929059171148608295'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/linux-server-ssh.html' title='Linux Server SSH'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8889344519163073736</id><published>2011-08-28T11:05:00.006-04:00</published><updated>2011-08-28T12:57:51.774-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Linux Server</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial;"&gt;A couple of weeks ago I &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-1.html"&gt;described&lt;/a&gt; installation of Ubuntu Linux (11.04), running under Virtual Box on Mac OS X Lion.  I got matplotlib (and scipy) &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-2.html"&gt;installed&lt;/a&gt; and running without any difficulty using &lt;code&gt;apt-get&lt;/code&gt; alone.&lt;br /&gt;&lt;br /&gt;Next, I &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-3.html"&gt;installed&lt;/a&gt; Apache Server 2.2 and configured everything to run Python scripts by using Firefox from Ubuntu on the VM like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;localhost/cgi-bin/test.py&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;After &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-4.html"&gt;struggling&lt;/a&gt; a bit, I &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-5.html"&gt;figured out&lt;/a&gt; how to use Virtual Box in NAT mode to do "port forwarding"---by modifying&lt;br /&gt;&lt;br /&gt;&lt;code&gt;/etc/apache2/sites-available/default&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;so then I could launch the script from the host OS by doing&lt;br /&gt;&lt;br /&gt;&lt;code&gt;localhost:8080/cgi-bin/test.py&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;from Safari or by using curl in Terminal.&lt;br /&gt;&lt;br /&gt;The next step was to try to access the server from a second machine on my home network.  In order to do that, (as I understand it) I can either remain in NAT mode and try to connect via the host machine and port-forwarding, or &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-6.html"&gt;use "bridging" mode&lt;/a&gt; to effectively put the Ubuntu server on the network.&lt;br /&gt;&lt;br /&gt;In order to accomplish this, I need to know the ip address of the server as assigned by my Apple Time Capsule router.  Now the problem is that this ip address may change with time (since we're getting it from the Time Capsule as a DHCP server).  According to the folks I asked on &lt;a href="http://serverfault.com/questions/300668/access-guest-os-server-under-virtualbox?s=514e64b8-ab73-499b-84df-f42951b9beeb"&gt;serverfault&lt;/a&gt;, I need to &lt;a href="http://www.liberiangeek.net/2011/03/configure-permanent-static-ip-addresses-ubuntu-11-04-natty-narwhal/"&gt;switch&lt;/a&gt; the Ubuntu network IPv4 settings to manual and ask for a specific ip address and this is correct so far as it goes.  &lt;br /&gt;&lt;br /&gt;However, the address I ask for in Ubuntu&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;&lt;a href="http://1.bp.blogspot.com/-b6WU-uVDyIU/TlpWggJ-0sI/AAAAAAAABw0/Tz2kVG383qE/s1600/Screen%2BShot%2B2011-08-28%2Bat%2B10.41.41%2BAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/-b6WU-uVDyIU/TlpWggJ-0sI/AAAAAAAABw0/Tz2kVG383qE/s320/Screen%2BShot%2B2011-08-28%2Bat%2B10.41.41%2BAM.png" width="269" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;&lt;br /&gt;has to match the range of addresses that the router is set up to hand out.  Furthermore, we probably want to have most ip addresses handled dynamically, and only use a static ip for the one machine.  If we wanted them all static, we'd go here:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-KC3CmvF_WwU/Tlpa79RpddI/AAAAAAAABxU/F6_95UCVUA0/s1600/Screen%2Bshot%2B2011-08-28%2Bat%2B11.12.18%2BAM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="167" width="320" src="http://1.bp.blogspot.com/-KC3CmvF_WwU/Tlpa79RpddI/AAAAAAAABxU/F6_95UCVUA0/s320/Screen%2Bshot%2B2011-08-28%2Bat%2B11.12.18%2BAM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I found the answer &lt;a href="http://www.wesg.ca/2008/08/set-up-a-static-ip-with-an-airport-base-station/"&gt;here&lt;/a&gt; but the setting is actually visible in this screenshot:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-bb_cZPF14X0/TlpWgv4FFsI/AAAAAAAABw8/O0KORcmPfDE/s1600/Screen%2Bshot%2B2011-08-28%2Bat%2B10.43.37%2BAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="319" src="http://4.bp.blogspot.com/-bb_cZPF14X0/TlpWgv4FFsI/AAAAAAAABw8/O0KORcmPfDE/s320/Screen%2Bshot%2B2011-08-28%2Bat%2B10.43.37%2BAM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Under Internet &amp;gt; DHCP there is a TableView called DHCP reservations.  I just reserved the first available ip address.  After re-booting Ubuntu and restarting the server, I can run the test script or do:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ISu5OZqBLKA/TlpWhN-jKyI/AAAAAAAABxM/HpvWLOeV6qM/s1600/Screen%2Bshot%2B2011-08-28%2Bat%2B10.48.07%2BAM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="237" src="http://4.bp.blogspot.com/-ISu5OZqBLKA/TlpWhN-jKyI/AAAAAAAABxM/HpvWLOeV6qM/s320/Screen%2Bshot%2B2011-08-28%2Bat%2B10.48.07%2BAM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now I have to figure out how to access the server from the outside world.  I should probably remove the test script from &lt;code&gt;cgi-bin&lt;/code&gt; (since it reveals information about paths on the server) and read up on firewall configuration, etc. before I do that.  The first problem for this part (not yet solved) is that my ip address from my isp, obtained with&lt;br /&gt;&lt;br /&gt;&lt;code&gt;checkip.dyndns.org/&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;does not seem to be accessible.  I get a "Safari can't connect to the server .." message.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8889344519163073736?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8889344519163073736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8889344519163073736' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8889344519163073736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8889344519163073736'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/linux-server.html' title='Linux Server'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-b6WU-uVDyIU/TlpWggJ-0sI/AAAAAAAABw0/Tz2kVG383qE/s72-c/Screen%2BShot%2B2011-08-28%2Bat%2B10.41.41%2BAM.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1458822804112361216</id><published>2011-08-27T09:25:00.012-04:00</published><updated>2011-08-27T12:47:42.837-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='what we&apos;re reading'/><title type='text'>Misunderstanding Euclid</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Category:  things you thought you knew that are wrong&lt;br /&gt;Today's entry is from &lt;a href="http://mathoverflow.net/questions/23478/examples-of-common-false-beliefs-in-mathematics"&gt;mathoverflow&lt;/a&gt;:&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;Many students believe that 1 plus the product of the first n primes is always a prime number. They have misunderstood the contradiction in Euclid's proof that there are infinitely many primes. (By the way, 2 * 3 * 5 * 7 * 11 * 13 + 1 is not prime.)&lt;br /&gt;&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;Let's ask Python:&lt;br /&gt;&lt;br /&gt;&lt;code&gt; &lt;div style="overflow-x: scroll "&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;from math import sqrt&lt;br /&gt;def f(N):&lt;br /&gt;    N += 1&lt;br /&gt;    print 'N', N&lt;br /&gt;    n = int(sqrt(N))&lt;br /&gt;    for i in range(2, n+1):&lt;br /&gt;        if not N % i:&lt;br /&gt;            print i, N/i&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; N = 2*3*5*7*11*13&lt;br /&gt;&gt;&gt;&gt; f(N)&lt;br /&gt;N 30031&lt;br /&gt;59 509&lt;br /&gt;&gt;&gt;&gt; N *= 17&lt;br /&gt;&gt;&gt;&gt; f(N)&lt;br /&gt;N 510511&lt;br /&gt;19 26869&lt;br /&gt;97 5263&lt;br /&gt;277 1843&lt;br /&gt;&gt;&gt;&gt; N *= 19&lt;br /&gt;&gt;&gt;&gt; f(N)&lt;br /&gt;N 9699691&lt;br /&gt;347 27953&lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;/code&gt;&lt;br /&gt;What the theorem actually says (&lt;a href="http://en.wikipedia.org/wiki/Euclid's_theorem"&gt;wikipedia&lt;/a&gt;):&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;Take any finite list of prime numbers p&lt;sub&gt;1&lt;/sub&gt;, p&lt;sub&gt;2&lt;/sub&gt;, ..., p&lt;sub&gt;n&lt;/sub&gt;. It will be shown that at least one additional prime number not in this list exists. Let P be the product of all the prime numbers in the list: P = p&lt;sub&gt;1&lt;/sub&gt;p&lt;sub&gt;2&lt;/sub&gt;...p&lt;sub&gt;n&lt;/sub&gt;. Let q = P + 1. &lt;br /&gt;&lt;br /&gt;Then, q is either prime or not:&lt;br /&gt;&lt;br /&gt;If q is prime then there is at least one more prime than is listed.&lt;br /&gt;&lt;br /&gt;If q is not prime then some prime factor p divides q. This factor p is not on our list: if it were, then it would divide P (since P is the product of every number on the list); but as we know, p divides P + 1 = q. Then p would have to divide the difference of the two numbers, which is (P + 1) − P or just 1. But no prime number divides 1 so there would be a contradiction, and therefore p cannot be on the list. This means at least one more prime number exists beyond those in the list.&lt;/blockquote&gt;&lt;/font&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1458822804112361216?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1458822804112361216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1458822804112361216' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1458822804112361216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1458822804112361216'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/misunderstanding-euclid.html' title='Misunderstanding Euclid'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3859991611059011894</id><published>2011-08-27T04:48:00.001-04:00</published><updated>2011-08-27T04:58:49.313-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='what we&apos;re reading'/><title type='text'>Late nights on the web</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;This is just a short post to document some interesting links.  I recently &lt;a href="http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion-revised.html"&gt;posted&lt;/a&gt; about getting matplotlib installed with minimum fuss on OS X Lion, and this seems to have helped quite a few folks.&lt;br /&gt;&lt;br /&gt;The person who &lt;a href="http://the.taoofmac.com/space/blog/2011/07/24/2222"&gt;showed&lt;/a&gt; me how to do this is named Rui Carmo, and I finally found the time to begin browsing through his extensive site;  he has lots of good stuff about Macs and other technology (like &lt;a href="http://the.taoofmac.com/space/HOWTO/Switch/Apps"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Perhaps the most interesting thing I found is what appears to be a very high quality company called &lt;a href="http://www.linode.com/"&gt;Linode&lt;/a&gt;, offering Linux Virtual Servers in the cloud, their docs include an extensive library related to the topic.  I'm thinking seriously about trying it (it only costs just a bit more than the NY Times). &lt;br /&gt;&lt;br /&gt;And the final result (of browsing the web on a sleepless night) is to note the profusion of different sites connected to &lt;a href="http://stackoverflow.com/"&gt;Stack Overflow&lt;/a&gt;, including &lt;a href="http://serverfault.com/"&gt;serverfault&lt;/a&gt; and &lt;a href="http://superuser.com/"&gt;superuser&lt;/a&gt;.  Very rewarding to browse through Q &amp; A, and of course, when I have a question of my own.&lt;br /&gt;&lt;br /&gt;One more thing:  a pdf form-filler &lt;a href="http://www.pdfescape.com/"&gt;link&lt;/a&gt; that is not Adobe.  One of the sites I use for work has Adobe forms on it that I can only read through Safari if I have Reader installed as the &lt;i&gt;default&lt;/i&gt; pdf viewer.  Maybe it will help with this, since I loathe Adobe.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3859991611059011894?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3859991611059011894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3859991611059011894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3859991611059011894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3859991611059011894'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/late-nights-on-web.html' title='Late nights on the web'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3264213640179888422</id><published>2011-08-24T18:38:00.023-04:00</published><updated>2011-08-24T18:52:22.127-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pretty code'/><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><title type='text'>Pretty code (6)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;This is absolutely the last post about html and code stuff.  The whole adventure started &lt;a href="http://telliott99.blogspot.com/2011/08/test_14.html"&gt;here&lt;/a&gt;.  It's a bit amusing to realize that if I had just understood what &amp;lt;br&gt; tags were about (and &amp;lt;span&gt; and &amp;lt;div&gt;), this would never have happened.&lt;br /&gt;&lt;br /&gt;I decided to write my own parser for Python code, so that I could post the results here.  On the way, I learned something about "styles" and stylesheets.  To organize things, I put this code for a "style" in the template for the blog at the end of &amp;lt;head&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;style type='text/css'&gt;&lt;br /&gt;div.content&lt;br /&gt;{&lt;br /&gt;font-size:12pt;&lt;br /&gt;font-family:arial;&lt;br /&gt;color: #404040;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;div.code&lt;br /&gt;{ &lt;br /&gt;font-size:12pt;&lt;br /&gt;font-family:courier;&lt;br /&gt;margin: 20px;&lt;br /&gt;border-style: solid;&lt;br /&gt;padding: 5px;&lt;br /&gt;border-width: 1px;&lt;br /&gt;border-color:#ff00ff;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;span.kw   { color:blue; }&lt;br /&gt;span.str  { color:red; }&lt;br /&gt;span.str3 { color:purple; }&lt;br /&gt;span.py   { color:#00b0b0; }&lt;br /&gt;span.cm   { color:green; }&lt;br /&gt;&amp;lt;/style&gt;&lt;/pre&gt;&lt;br /&gt;The parser output looks great when run on itself.  The first little bit is here:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-9gdpEEhT8q0/TlWAGiKaOAI/AAAAAAAABwg/_tpqXQJuxFs/s1600/Screen%2Bshot%2B2011-08-24%2Bat%2B6.49.35%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="282" width="320" src="http://4.bp.blogspot.com/-9gdpEEhT8q0/TlWAGiKaOAI/AAAAAAAABwg/_tpqXQJuxFs/s320/Screen%2Bshot%2B2011-08-24%2Bat%2B6.49.35%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;But, alas, it was not to be.  The Blogger editor is now (still) messing with my code, removing all the &amp;lt;br /&gt; that I carefully put in, so that the informative whitespace is gone in the actual post (though not in the intial preview before posting).  It looks hopeless at this point.&lt;br /&gt;&lt;br /&gt;Files for the parser on Dropbox (&lt;a href="http://dl.dropbox.com/u/3534458/pyparser.zip"&gt;here&lt;/a&gt;).  The only known bugs are those visible in the comment lines above, where the strings should have been masked by being inside a comment.&lt;br /&gt;&lt;br /&gt;Unfortunately, I do not know how to make this all work for Blogger.&lt;br /&gt;&lt;br /&gt;What a waste!  I am not happy with these guys.  The only way I can see is to have my own server.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3264213640179888422?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3264213640179888422/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3264213640179888422' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3264213640179888422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3264213640179888422'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/pretty-code-6.html' title='Pretty code (6)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-9gdpEEhT8q0/TlWAGiKaOAI/AAAAAAAABwg/_tpqXQJuxFs/s72-c/Screen%2Bshot%2B2011-08-24%2Bat%2B6.49.35%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8219222843611345902</id><published>2011-08-22T22:05:00.000-04:00</published><updated>2011-08-22T22:05:06.751-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pretty code'/><title type='text'>Pretty code (5)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;This is the first section of the same example from the last post (&lt;a href="http://telliott99.blogspot.com/2011/08/pretty-code-4.html"&gt;here&lt;/a&gt;, more explanation &lt;a href="http://telliott99.blogspot.com/2011/08/pretty-code-3.html"&gt;here&lt;/a&gt;), run through &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt;.  It is self-contained and doesn't require loading any other resources.&lt;br /&gt;&lt;br /&gt;The code to generate it was:&lt;br /&gt;&lt;pre&gt;&gt; pygmentize -f html -O full -o test.html pyparser.py&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is the same parser that is used for the official Python docs, which are generated in combination with Sphinx.  I have only a hazy idea of how that's done.&lt;br /&gt;&lt;br /&gt;It's easily customizable if you want.&lt;br /&gt;&lt;br /&gt;  &lt;style type="text/css"&gt;td.linenos { background-color: #f0f0f0; padding-right: 10px; }span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }pre { line-height: 125%; }body .hll { background-color: #ffffcc }body  { background: #f8f8f8; }body .c { color: #408080; font-style: italic } /* Comment */body .err { border: 1px solid #FF0000 } /* Error */body .k { color: #008000; font-weight: bold } /* Keyword */body .o { color: #666666 } /* Operator */body .cm { color: #408080; font-style: italic } /* Comment.Multiline */body .cp { color: #BC7A00 } /* Comment.Preproc */body .c1 { color: #408080; font-style: italic } /* Comment.Single */body .cs { color: #408080; font-style: italic } /* Comment.Special */body .gd { color: #A00000 } /* Generic.Deleted */body .ge { font-style: italic } /* Generic.Emph */body .gr { color: #FF0000 } /* Generic.Error */body .gh { color: #000080; font-weight: bold } /* Generic.Heading */body .gi { color: #00A000 } /* Generic.Inserted */body .go { color: #808080 } /* Generic.Output */body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */body .gs { font-weight: bold } /* Generic.Strong */body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */body .gt { color: #0040D0 } /* Generic.Traceback */body .kc { color: #008000; font-weight: bold } /* Keyword.Constant */body .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */body .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */body .kp { color: #008000 } /* Keyword.Pseudo */body .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */body .kt { color: #B00040 } /* Keyword.Type */body .m { color: #666666 } /* Literal.Number */body .s { color: #BA2121 } /* Literal.String */body .na { color: #7D9029 } /* Name.Attribute */body .nb { color: #008000 } /* Name.Builtin */body .nc { color: #0000FF; font-weight: bold } /* Name.Class */body .no { color: #880000 } /* Name.Constant */body .nd { color: #AA22FF } /* Name.Decorator */body .ni { color: #999999; font-weight: bold } /* Name.Entity */body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */body .nf { color: #0000FF } /* Name.Function */body .nl { color: #A0A000 } /* Name.Label */body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */body .nt { color: #008000; font-weight: bold } /* Name.Tag */body .nv { color: #19177C } /* Name.Variable */body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */body .w { color: #bbbbbb } /* Text.Whitespace */body .mf { color: #666666 } /* Literal.Number.Float */body .mh { color: #666666 } /* Literal.Number.Hex */body .mi { color: #666666 } /* Literal.Number.Integer */body .mo { color: #666666 } /* Literal.Number.Oct */body .sb { color: #BA2121 } /* Literal.String.Backtick */body .sc { color: #BA2121 } /* Literal.String.Char */body .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */body .s2 { color: #BA2121 } /* Literal.String.Double */body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */body .sh { color: #BA2121 } /* Literal.String.Heredoc */body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */body .sx { color: #008000 } /* Literal.String.Other */body .sr { color: #BB6688 } /* Literal.String.Regex */body .s1 { color: #BA2121 } /* Literal.String.Single */body .ss { color: #19177C } /* Literal.String.Symbol */body .bp { color: #008000 } /* Name.Builtin.Pseudo */body .vc { color: #19177C } /* Name.Variable.Class */body .vg { color: #19177C } /* Name.Variable.Global */body .vi { color: #19177C } /* Name.Variable.Instance */body .il { color: #666666 } /* Literal.Number.Integer.Long */  &lt;/style&gt;&lt;br /&gt;&lt;h2&gt;&lt;/h2&gt;&lt;br /&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;keyword&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;kwlist&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;punctuation&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;punct&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_data&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;html_tags&lt;/span&gt; &lt;span class="kn"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;H&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;pywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;True&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;False&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;list&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;dict&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;           &lt;span class="s"&gt;&amp;#39;int&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;float&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;append&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;extend&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;           &lt;span class="s"&gt;&amp;#39;sys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;argv&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;pop&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;open&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;write&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;           &lt;span class="s"&gt;&amp;#39;close&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;string&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;br /&gt;    &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;IndexError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;br /&gt;    &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;example.py&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8219222843611345902?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8219222843611345902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8219222843611345902' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8219222843611345902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8219222843611345902'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/pretty-code-5.html' title='Pretty code (5)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8218049141874987509</id><published>2011-08-22T15:54:00.000-04:00</published><updated>2011-08-22T15:54:12.716-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pretty code'/><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><title type='text'>Pretty code (4)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Explanation of what this is about from last time &lt;a href="http://telliott99.blogspot.com/2011/08/pretty-code-3.html"&gt;here&lt;/a&gt;.  I got triple-quoted strings working, and I'm really pleased with the results.  More another time on other options for code-highlighting.&lt;style&gt;  cd { font-size:120%; }  cm { color: green }  kw { color: blue; }  str { color: red; }  str3 { color: #ff7f50 }  py { color: #9400d3 }&lt;/style&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;hr&gt;&lt;kw&gt;import&lt;/kw&gt; &lt;py&gt;sys&lt;/py&gt;&lt;br /&gt;&lt;kw&gt;from&lt;/kw&gt; keyword &lt;kw&gt;import&lt;/kw&gt; kwlist&lt;br /&gt;&lt;kw&gt;from&lt;/kw&gt; &lt;py&gt;string&lt;/py&gt; &lt;kw&gt;import&lt;/kw&gt; punctuation &lt;kw&gt;as&lt;/kw&gt; punct&lt;br /&gt;&lt;kw&gt;from&lt;/kw&gt; utils &lt;kw&gt;import&lt;/kw&gt; load_data&lt;br /&gt;&lt;kw&gt;import&lt;/kw&gt; html_tags &lt;kw&gt;as&lt;/kw&gt; H&lt;br /&gt;pywords = [&lt;str&gt;'&lt;py&gt;True&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;False&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;list&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;dict&lt;/py&gt;'&lt;/str&gt;,&lt;br /&gt;           &lt;str&gt;'&lt;py&gt;int&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;float&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;append&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;extend&lt;/py&gt;'&lt;/str&gt;,&lt;br /&gt;           &lt;str&gt;'&lt;py&gt;sys&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;argv&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;pop&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;open&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;write&lt;/py&gt;'&lt;/str&gt;,&lt;br /&gt;           &lt;str&gt;'&lt;py&gt;close&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;string&lt;/py&gt;'&lt;/str&gt;,&lt;str&gt;'&lt;py&gt;time&lt;/py&gt;'&lt;/str&gt;]&lt;br /&gt;&lt;br /&gt;try:  &lt;br /&gt;    fn = &lt;py&gt;sys&lt;/py&gt;.&lt;py&gt;argv&lt;/py&gt;[1]&lt;br /&gt;&lt;kw&gt;except&lt;/kw&gt; IndexError:  &lt;br /&gt;    fn = &lt;str&gt;'example.py'&lt;/str&gt;&lt;br /&gt;data = &lt;py&gt;list&lt;/py&gt;(load_data(fn))&lt;br /&gt;&lt;br /&gt;D = {&lt;str&gt;'is_cm'&lt;/str&gt;:&lt;py&gt;False&lt;/py&gt;,&lt;br /&gt;     &lt;str&gt;'in_str_1'&lt;/str&gt;:&lt;py&gt;False&lt;/py&gt;,&lt;br /&gt;     &lt;str&gt;'in_str_2'&lt;/str&gt;:&lt;py&gt;False&lt;/py&gt;,&lt;br /&gt;     &lt;str&gt;'in_str_3'&lt;/str&gt;:&lt;py&gt;False&lt;/py&gt; }&lt;br /&gt;&lt;br /&gt;L = &lt;py&gt;list&lt;/py&gt;()&lt;br /&gt;&lt;br /&gt;&lt;kw&gt;while&lt;/kw&gt; data:&lt;br /&gt;    c = data.&lt;py&gt;pop&lt;/py&gt;(0)&lt;br /&gt;    &lt;cm&gt;# comments first&lt;/cm&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;'#'&lt;/str&gt;:&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; (D[&lt;str&gt;'in_str_1'&lt;/str&gt;] &lt;kw&gt;or&lt;/kw&gt; D[&lt;str&gt;'in_str_2'&lt;/str&gt;]):&lt;br /&gt;            L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.cm_start))&lt;br /&gt;            D[&lt;str&gt;'is_cm'&lt;/str&gt;] = &lt;py&gt;True&lt;/py&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;"\n"&lt;/str&gt; &lt;kw&gt;and&lt;/kw&gt; D[&lt;str&gt;'is_cm'&lt;/str&gt;]:&lt;br /&gt;        L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.cm_stop))&lt;br /&gt;        D[&lt;str&gt;'is_cm'&lt;/str&gt;] = &lt;py&gt;False&lt;/py&gt;&lt;br /&gt;    L.&lt;py&gt;append&lt;/py&gt;(c)&lt;br /&gt;    &lt;br /&gt;    a = &lt;str3&gt;'''triple-quoted-string&lt;br /&gt;    with a continuation and two keywords'''&lt;/str3&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;cm&gt;# triple-quoted strings&lt;/cm&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;"'"&lt;/str&gt; &lt;kw&gt;and&lt;/kw&gt; len(data) &gt; 1:&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; data[0] == &lt;str&gt;"'"&lt;/str&gt; &lt;kw&gt;and&lt;/kw&gt; data[1] == &lt;str&gt;"'"&lt;/str&gt;:&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; (&lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'in_str_1'&lt;/str&gt;] &lt;kw&gt;and&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'in_str_2'&lt;/str&gt;]):&lt;br /&gt;                &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'in_str_3'&lt;/str&gt;]:&lt;br /&gt;                    L.&lt;py&gt;pop&lt;/py&gt;()&lt;br /&gt;                    L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.str3_start))&lt;br /&gt;                    L.&lt;py&gt;extend&lt;/py&gt;([&lt;str&gt;"'"&lt;/str&gt;] * 3)&lt;br /&gt;                    data.&lt;py&gt;pop&lt;/py&gt;(0)&lt;br /&gt;                    data.&lt;py&gt;pop&lt;/py&gt;(0)&lt;br /&gt;                    D[&lt;str&gt;'in_str_3'&lt;/str&gt;] = &lt;py&gt;True&lt;/py&gt;&lt;br /&gt;                else:&lt;br /&gt;                    data.&lt;py&gt;pop&lt;/py&gt;(0)&lt;br /&gt;                    data.&lt;py&gt;pop&lt;/py&gt;(0)&lt;br /&gt;                    L.&lt;py&gt;extend&lt;/py&gt;([&lt;str&gt;"'"&lt;/str&gt;] * 2)&lt;br /&gt;                    L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.str3_stop))&lt;br /&gt;                    D[&lt;str&gt;'in_str_3'&lt;/str&gt;] = &lt;py&gt;False&lt;/py&gt;&lt;br /&gt;                    &lt;kw&gt;continue&lt;/kw&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;cm&gt;# single-quoted strings&lt;/cm&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;"'"&lt;/str&gt;:&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; D[&lt;str&gt;'in_str_3'&lt;/str&gt;]:&lt;br /&gt;            &lt;kw&gt;continue&lt;/kw&gt;        &lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; (not D[&lt;str&gt;'in_str_1'&lt;/str&gt;]):&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'in_str_2'&lt;/str&gt;]:&lt;br /&gt;                &lt;cm&gt;# start a str_1&lt;/cm&gt;&lt;br /&gt;                L.&lt;py&gt;pop&lt;/py&gt;()&lt;br /&gt;                L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.str_start))&lt;br /&gt;                L.&lt;py&gt;append&lt;/py&gt;(c)&lt;br /&gt;                D[&lt;str&gt;'in_str_1'&lt;/str&gt;] = &lt;py&gt;True&lt;/py&gt;&lt;br /&gt;            else:&lt;br /&gt;                &lt;cm&gt;# already in str_2 or str_3&lt;/cm&gt;&lt;br /&gt;                &lt;kw&gt;pass&lt;/kw&gt;&lt;br /&gt;        else:&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; D[&lt;str&gt;'in_str_1'&lt;/str&gt;]:&lt;br /&gt;                &lt;cm&gt;# terminate str_1    &lt;/cm&gt;&lt;br /&gt;                L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.str_stop))&lt;br /&gt;                D[&lt;str&gt;'in_str_1'&lt;/str&gt;] = &lt;py&gt;False&lt;/py&gt;&lt;br /&gt;            &lt;br /&gt;    &lt;cm&gt;# double-quoted strings&lt;/cm&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;'"'&lt;/str&gt;:&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;&lt;kw&gt;not&lt;/kw&gt;&lt;/kw&gt; D[&lt;str&gt;'in_str_2'&lt;/str&gt;] &lt;kw&gt;and&lt;/kw&gt; &lt;kw&gt;&lt;kw&gt;not&lt;/kw&gt;&lt;/kw&gt; D[&lt;str&gt;'in_str_3'&lt;/str&gt;]:&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'in_str_1'&lt;/str&gt;]:&lt;br /&gt;                &lt;cm&gt;# start a str_2&lt;/cm&gt;&lt;br /&gt;                L.&lt;py&gt;pop&lt;/py&gt;()&lt;br /&gt;                L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.str_start))&lt;br /&gt;                L.&lt;py&gt;append&lt;/py&gt;(c)&lt;br /&gt;                D[&lt;str&gt;'in_str_2'&lt;/str&gt;] = &lt;py&gt;True&lt;/py&gt;&lt;br /&gt;            else:&lt;br /&gt;                &lt;cm&gt;# already in str_1 or str_3&lt;/cm&gt;&lt;br /&gt;                &lt;kw&gt;pass&lt;/kw&gt;&lt;br /&gt;        else:&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; D[&lt;str&gt;'in_str_2'&lt;/str&gt;]:&lt;br /&gt;                &lt;cm&gt;# terminate str_2    &lt;/cm&gt;&lt;br /&gt;                L.&lt;py&gt;extend&lt;/py&gt;(&lt;py&gt;list&lt;/py&gt;(H.str_stop))&lt;br /&gt;                D[&lt;str&gt;'in_str_2'&lt;/str&gt;] = &lt;py&gt;False&lt;/py&gt;&lt;br /&gt;s = &lt;str&gt;''&lt;/str&gt;.join(L)&lt;br /&gt;&lt;br /&gt;&lt;cm&gt;# keywords last&lt;/cm&gt;&lt;br /&gt;pL = &lt;py&gt;list&lt;/py&gt;()&lt;br /&gt;D[&lt;str&gt;'is_str_3'&lt;/str&gt;] = &lt;py&gt;False&lt;/py&gt;&lt;br /&gt;&lt;kw&gt;for&lt;/kw&gt; l&lt;kw&gt;in&lt;/kw&gt;e &lt;kw&gt;in&lt;/kw&gt; s.split(&lt;str&gt;'\n'&lt;/str&gt;):&lt;br /&gt;    D[&lt;str&gt;'is_cm'&lt;/str&gt;] = &lt;py&gt;False&lt;/py&gt;&lt;br /&gt;    words = line.split()&lt;br /&gt;    &lt;kw&gt;for&lt;/kw&gt; w &lt;kw&gt;in&lt;/kw&gt; words:&lt;br /&gt;        &lt;cm&gt;# no kw highlighting in comments&lt;/cm&gt;&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; w.startswith(H.cm_start):&lt;br /&gt;            D[&lt;str&gt;'is_cm'&lt;/str&gt;] = &lt;py&gt;True&lt;/py&gt;&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; w.startswith(H.str3_start):&lt;br /&gt;            D[&lt;str&gt;'is_str_3'&lt;/str&gt;] = &lt;py&gt;True&lt;/py&gt;&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; H.str3_stop &lt;kw&gt;in&lt;/kw&gt; w:&lt;br /&gt;            D[&lt;str&gt;'is_str_3'&lt;/str&gt;] = &lt;py&gt;False&lt;/py&gt;&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;&lt;kw&gt;not&lt;/kw&gt;&lt;/kw&gt; D[&lt;str&gt;'is_cm'&lt;/str&gt;] &lt;kw&gt;and&lt;/kw&gt; &lt;kw&gt;&lt;kw&gt;not&lt;/kw&gt;&lt;/kw&gt; D[&lt;str&gt;'is_str_3'&lt;/str&gt;]:&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; w &lt;kw&gt;in&lt;/kw&gt; kwlist:&lt;br /&gt;                r = H.kw_start + w + H.kw_stop&lt;br /&gt;                line = line.replace(w, r)&lt;br /&gt;            &lt;kw&gt;for&lt;/kw&gt; p &lt;kw&gt;in&lt;/kw&gt; pywords:&lt;br /&gt;                &lt;kw&gt;if&lt;/kw&gt; p &lt;kw&gt;in&lt;/kw&gt; w:&lt;br /&gt;                    L = w.split(p)&lt;br /&gt;                    &lt;kw&gt;if&lt;/kw&gt; L[0] &lt;kw&gt;and&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; L[0][-1] &lt;kw&gt;in&lt;/kw&gt; punct:&lt;br /&gt;                        &lt;kw&gt;continue&lt;/kw&gt;&lt;br /&gt;                    &lt;kw&gt;if&lt;/kw&gt; L[1] &lt;kw&gt;and&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; L[1][0] &lt;kw&gt;in&lt;/kw&gt; punct:&lt;br /&gt;                        &lt;kw&gt;continue&lt;/kw&gt;&lt;br /&gt;                    r = H.py_start + p + H.py_stop&lt;br /&gt;                    line = line.replace(p, r)&lt;br /&gt;    pL.&lt;py&gt;append&lt;/py&gt;(line)&lt;br /&gt;    &lt;br /&gt;s = H.br.join(pL)&lt;br /&gt;pL = [H.head, H.hr, s, H.hr, H.tail]&lt;br /&gt;s = &lt;str&gt;'\n'&lt;/str&gt;.join(pL)&lt;br /&gt;&lt;br /&gt;fn = fn.split(&lt;str&gt;'.'&lt;/str&gt;)[0] + &lt;str&gt;'.html'&lt;/str&gt;&lt;br /&gt;FH = &lt;py&gt;open&lt;/py&gt;(fn,&lt;str&gt;'w'&lt;/str&gt;)&lt;br /&gt;FH.&lt;py&gt;write&lt;/py&gt;(s + &lt;str&gt;'\n'&lt;/str&gt;)&lt;br /&gt;FH.&lt;py&gt;close&lt;/py&gt;()&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's a screenshot of &lt;code&gt;html_tags.py&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-LEvc-ox5rsM/TlKyKGsJ9JI/AAAAAAAABwY/4Yi-HSMzPZM/s1600/Screen%2Bshot%2B2011-08-22%2Bat%2B3.43.17%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="176" src="http://2.bp.blogspot.com/-LEvc-ox5rsM/TlKyKGsJ9JI/AAAAAAAABwY/4Yi-HSMzPZM/s320/Screen%2Bshot%2B2011-08-22%2Bat%2B3.43.17%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8218049141874987509?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8218049141874987509/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8218049141874987509' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8218049141874987509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8218049141874987509'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/pretty-code-4.html' title='Pretty code (4)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-LEvc-ox5rsM/TlKyKGsJ9JI/AAAAAAAABwY/4Yi-HSMzPZM/s72-c/Screen%2Bshot%2B2011-08-22%2Bat%2B3.43.17%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-6666917900644792497</id><published>2011-08-22T06:32:00.013-04:00</published><updated>2011-08-22T07:33:24.044-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pretty code'/><title type='text'>Pretty code (3)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I worked a bit more on the Python parser that I described last time (&lt;a href="http://telliott99.blogspot.com/2011/08/pretty-code-2.html"&gt;here&lt;/a&gt;).  Actually, I started over from scratch.  The first approach was based on breaking the code into words for processing, but I realized that a "stream" approach of one character at a time is better.  The only limitation I'm aware of is that I still don't handle triple-quoted strings, but I think it's doable in the future.&lt;br /&gt;&lt;br /&gt;As I mentioned before, I'm using &amp;lt;br /&gt; tags in the code now rather than newlines.&lt;br /&gt;&lt;br /&gt;The instructions for doing this said to modify the blog template, but I'm afraid of breaking the formatting for old posts.  I put the following just below the &amp;lt;body&gt; tag instead, as shown.  It seems to work.&lt;br /&gt;&lt;pre&gt;&amp;lt;body&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;style&gt;&lt;br /&gt;  cd { font-size:120%; }&lt;br /&gt;  cm { color: green }&lt;br /&gt;  kw { color: blue; }&lt;br /&gt;  str { color: red; }&lt;br /&gt;&amp;lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then, to be totally meta about it, I ran the parser on itself.  It is set up to grab HTML tags from a separate file (otherwise the meta application chokes on the tags).   They are the ones shown above.  Plus, there is a head and a tail to make an independent .html document.  But for pasting into the blog, you don't need those guys.  I invoked it like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;python simple_parser2.py simple_parser2.py &gt; example.html&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And here is the code:&lt;br /&gt;&lt;style&gt;  cd { font-size:120%; }  cm { color: green }  kw { color: blue; }  str { color: red; }&lt;/style&gt;&lt;br /&gt;&lt;pre&gt;&lt;cd&gt;&lt;br /&gt;&lt;hr&gt;&lt;kw&gt;import&lt;/kw&gt; sys&lt;br /&gt;&lt;kw&gt;from&lt;/kw&gt; keyword &lt;kw&gt;import&lt;/kw&gt; iskeyword&lt;br /&gt;&lt;kw&gt;from&lt;/kw&gt; utils &lt;kw&gt;import&lt;/kw&gt; load_data&lt;br /&gt;&lt;kw&gt;import&lt;/kw&gt; html_tags &lt;kw&gt;as&lt;/kw&gt; H&lt;br /&gt;&lt;br /&gt;try:  &lt;br /&gt;    fn = sys.argv[1]&lt;br /&gt;&lt;kw&gt;except&lt;/kw&gt; IndexError:  &lt;br /&gt;    fn = &lt;str&gt;'example.py'&lt;/str&gt;&lt;br /&gt;data = list(load_data(fn))&lt;br /&gt;&lt;br /&gt;D = {&lt;str&gt;'is_cm'&lt;/str&gt;:False,&lt;br /&gt;     &lt;str&gt;'is_str_1'&lt;/str&gt;:False,&lt;str&gt;'is_str_2'&lt;/str&gt;:False }&lt;br /&gt;&lt;br /&gt;L = list()&lt;br /&gt;&lt;kw&gt;for&lt;/kw&gt; c &lt;kw&gt;in&lt;/kw&gt; data:&lt;br /&gt;    &lt;cm&gt;# comments first&lt;/cm&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;'#'&lt;/str&gt;:&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; (D[&lt;str&gt;'is_str_1'&lt;/str&gt;] &lt;kw&gt;or&lt;/kw&gt; D[&lt;str&gt;'is_str_2'&lt;/str&gt;]):&lt;br /&gt;            L.extend(list(H.cm_start))&lt;br /&gt;            D[&lt;str&gt;'is_cm'&lt;/str&gt;] = True&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;"\n"&lt;/str&gt; &lt;kw&gt;and&lt;/kw&gt; D[&lt;str&gt;'is_cm'&lt;/str&gt;]:&lt;br /&gt;        L.extend(list(H.cm_stop))&lt;br /&gt;        D[&lt;str&gt;'is_cm'&lt;/str&gt;] = False&lt;br /&gt;    L.append(c)&lt;br /&gt;    &lt;br /&gt;    &lt;cm&gt;# single-quoted strings&lt;/cm&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;"'"&lt;/str&gt;:&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'is_str_1'&lt;/str&gt;]:&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'is_str_2'&lt;/str&gt;]:&lt;br /&gt;                &lt;cm&gt;# start a str_1&lt;/cm&gt;&lt;br /&gt;                L.pop()&lt;br /&gt;                L.extend(list(H.str_start))&lt;br /&gt;                L.append(c)&lt;br /&gt;                D[&lt;str&gt;'is_str_1'&lt;/str&gt;] = True&lt;br /&gt;            else:&lt;br /&gt;                &lt;cm&gt;# already in str_2&lt;/cm&gt;&lt;br /&gt;                &lt;kw&gt;pass&lt;/kw&gt;&lt;br /&gt;        else:&lt;br /&gt;            &lt;cm&gt;# terminate str_1    &lt;/cm&gt;&lt;br /&gt;            L.extend(list(H.str_stop))&lt;br /&gt;            D[&lt;str&gt;'is_str_1'&lt;/str&gt;] = False&lt;br /&gt;    &lt;cm&gt;# double-quoted strings&lt;/cm&gt;&lt;br /&gt;    &lt;kw&gt;if&lt;/kw&gt; c == &lt;str&gt;'"'&lt;/str&gt;:&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'is_str_2'&lt;/str&gt;]:&lt;br /&gt;            &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'is_str_1'&lt;/str&gt;]:&lt;br /&gt;                &lt;cm&gt;# start a str_2&lt;/cm&gt;&lt;br /&gt;                L.pop()&lt;br /&gt;                L.extend(list(H.str_start))&lt;br /&gt;                L.append(c)&lt;br /&gt;                D[&lt;str&gt;'is_str_2'&lt;/str&gt;] = True&lt;br /&gt;            else:&lt;br /&gt;                &lt;cm&gt;# already in str_1&lt;/cm&gt;&lt;br /&gt;                &lt;kw&gt;pass&lt;/kw&gt;&lt;br /&gt;        else:&lt;br /&gt;            &lt;cm&gt;# terminate str_2    &lt;/cm&gt;&lt;br /&gt;            L.extend(list(H.str_stop))&lt;br /&gt;            D[&lt;str&gt;'is_str_2'&lt;/str&gt;] = False&lt;br /&gt;s = &lt;str&gt;''&lt;/str&gt;.join(L)&lt;br /&gt;&lt;br /&gt;&lt;cm&gt;# keywords last&lt;/cm&gt;&lt;br /&gt;pL = list()&lt;br /&gt;&lt;kw&gt;for&lt;/kw&gt; l&lt;kw&gt;in&lt;/kw&gt;e &lt;kw&gt;in&lt;/kw&gt; s.split(&lt;str&gt;'\n'&lt;/str&gt;):&lt;br /&gt;    D[&lt;str&gt;'is_cm'&lt;/str&gt;] = False&lt;br /&gt;    words = line.split()&lt;br /&gt;    &lt;kw&gt;for&lt;/kw&gt; w &lt;kw&gt;in&lt;/kw&gt; words:&lt;br /&gt;        &lt;cm&gt;# no kw highlighting in comments&lt;/cm&gt;&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; w.startswith(H.cm_start):&lt;br /&gt;            D[&lt;str&gt;'is_cm'&lt;/str&gt;] = True&lt;br /&gt;        &lt;kw&gt;if&lt;/kw&gt; &lt;kw&gt;not&lt;/kw&gt; D[&lt;str&gt;'is_cm'&lt;/str&gt;] &lt;kw&gt;and&lt;/kw&gt; iskeyword(w):&lt;br /&gt;            r = H.kw_start + w + H.kw_stop&lt;br /&gt;            line = line.replace(w, r)&lt;br /&gt;    pL.append(line)&lt;br /&gt;s = H.br.join(pL)&lt;br /&gt;&lt;br /&gt;pL = [H.head, H.hr, s, H.hr, H.tail]&lt;br /&gt;s = &lt;str&gt;'\n'&lt;/str&gt;.join(pL)&lt;br /&gt;&lt;br /&gt;try:  &lt;br /&gt;    fn = sys.argv[2]&lt;br /&gt;&lt;kw&gt;except&lt;/kw&gt; IndexError:  &lt;br /&gt;    fn = &lt;str&gt;'example.html'&lt;/str&gt;&lt;br /&gt;FH = open(fn,&lt;str&gt;'w'&lt;/str&gt;)&lt;br /&gt;FH.write(s + &lt;str&gt;'\n'&lt;/str&gt;)&lt;br /&gt;FH.close()&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;/cd&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-6666917900644792497?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/6666917900644792497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=6666917900644792497' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6666917900644792497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6666917900644792497'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/pretty-code-3.html' title='Pretty code (3)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7444879504157936013</id><published>2011-08-21T19:56:00.005-04:00</published><updated>2011-08-21T20:05:12.794-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pretty code'/><title type='text'>Pretty code (2)</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-9j7uDk1MGQc/TlGapjygY-I/AAAAAAAABwI/i83gu52vIq8/s1600/Screen%2BShot%2B2011-08-21%2Bat%2B7.45.10%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="249" src="http://2.bp.blogspot.com/-9j7uDk1MGQc/TlGapjygY-I/AAAAAAAABwI/i83gu52vIq8/s320/Screen%2BShot%2B2011-08-21%2Bat%2B7.45.10%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;So the question is, what are the good ways to format code for blog posts, when you don't control the machine that serves the pages (like on &lt;a href="http://www.blogger.com/home"&gt;Blogger&lt;/a&gt;).  The first---and motivating---post in this series is &lt;a href="http://telliott99.blogspot.com/2011/08/test_14.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I always prefer simple to complex.  I even prefer simple html pages, although I'll ignore the obvious problem that pages are not simple any more when Blogger gets through with them.&lt;br /&gt;&lt;br /&gt;So I liked the idea of controlling the color of text in a page with self-defined tags.  For example, we can put this in the head of our html document:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-01rdwQfA6oY/TlGdBhfnsfI/AAAAAAAABwQ/-DDfqqFsYVg/s1600/Screen%2BShot%2B2011-08-21%2Bat%2B8.03.56%2BPM.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="246" width="320" src="http://1.bp.blogspot.com/-01rdwQfA6oY/TlGdBhfnsfI/AAAAAAAABwQ/-DDfqqFsYVg/s320/Screen%2BShot%2B2011-08-21%2Bat%2B8.03.56%2BPM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It's a seductively simple idea.  But.. it requires a way of parsing Python code to generate the appropriate tags.  I thought if I enforced some rules that could be done relatively easily.  &lt;br /&gt;&lt;br /&gt;After a few hours, I have something that sort of works, but it has too many bugs to be useful yet.&lt;br /&gt;&lt;br /&gt;The main simplifying rule is that multi-line strings are not allowed.  Also, at this point I assume that indentation is a four-space tab.&lt;br /&gt;&lt;br /&gt;You can see the results in the graphic (above).  I put the script on Dropbox (&lt;a href="http://dl.dropbox.com/u/3534458/simple_parser.py"&gt;simple_parser.py&lt;/a&gt;).  Without a lot more debugging, this seems like it's probably not the best option, but it was an entertaining exercise for the afternoon.&lt;span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7444879504157936013?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7444879504157936013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7444879504157936013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7444879504157936013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7444879504157936013'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/pretty-code-2.html' title='Pretty code (2)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-9j7uDk1MGQc/TlGapjygY-I/AAAAAAAABwI/i83gu52vIq8/s72-c/Screen%2BShot%2B2011-08-21%2Bat%2B7.45.10%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8364233307402788706</id><published>2011-08-21T08:56:00.001-04:00</published><updated>2011-08-22T07:27:14.959-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pretty code'/><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Formatting problem solved</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;[ UPDATE:  So I discovered that the line breaks setting below seems to be retroactive, and changing it messes up the old posts.  Another solution is to substitute newlines in the code with &amp;lt;br /&gt; tags.  That's what I've done here, and seems OK. This makes it difficult to actually edit code samples in the editor, but them's the breaks.  :) ]&lt;br /&gt;&lt;br /&gt;On the topic of how to format code samples for the blog, I've been doing some testing and found that the combination of &lt;br /&gt;&lt;code&gt;&lt;br /&gt;Settings &gt; Formatting&lt;br /&gt;section:  Convert line breaks&lt;br /&gt;No&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Settings &gt; Basic&lt;br /&gt;section:  Global &gt; Select post editor&lt;br /&gt;Updated editor&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;appears to have solved the problems that cropped up (my post &lt;a href="http://telliott99.blogspot.com/2011/08/test_14.html"&gt;here&lt;/a&gt;) with my standard approach using &amp;lt;table&gt;.  A sample:&lt;br /&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;def f(n):&lt;br /&gt;print "Hello world!"&lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And I like it that the new editor's preview mode gives an accurate view of the product.&lt;br /&gt;&lt;br /&gt;However, there are other solutions to consider, including how to get syntax highlighting without needing to load resources that are out of my control (my SO question is &lt;a href="http://stackoverflow.com/questions/7134780/formatting-python-code-for-the-web"&gt;here&lt;/a&gt;), or whether to use a code hosting service and "embed" the code here.  I'll have to get back to you on that.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8364233307402788706?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8364233307402788706/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8364233307402788706' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8364233307402788706'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8364233307402788706'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/formatting-problem-solved.html' title='Formatting problem solved'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-4609803609173593906</id><published>2011-08-20T11:04:00.015-04:00</published><updated>2011-08-21T09:14:14.247-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RPy2'/><category scheme='http://www.blogger.com/atom/ns#' term='Bioconductor'/><title type='text'>Bioonductor:  summary</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;[ Update:  Sorry for the dup.  I tried using the new formatting on this one, but found a problem, which I hope is fixed now.]&lt;br /&gt;&lt;br /&gt;I promise this is the last one.  Here we load the sample data from ExpressionSet.  I show (once again) how to obtain all the relevant stuff:  expression data, sample names, feature names, and gene names.&lt;br /&gt;&lt;br /&gt;One of the nice things about ExpressionSet objects is the very fancy indexing one can do with them.  A great example is given on p. 166 of the Bioconductor book.&lt;br /&gt; &lt;br /&gt;I made an stab at implementing range selectors here but it's almost trivial.  Also, in this one, the Python code does not contain any informative whitespace, so I've used the &amp;lt;code&gt; tag. &lt;br /&gt;The script is first and then the output.  If you can't figure something out, just ask.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;script.py&lt;/code&gt;&lt;br /&gt;&lt;div&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;import rpy2.robjects as robjects &lt;br /&gt;from rpy2.robjects.packages import importr  &lt;br /&gt;import rpy2.rinterface as ri  &lt;br /&gt;import bioc.biobase as biobase &lt;br /&gt;&lt;br /&gt;r = robjects.r &lt;br /&gt;g = robjects.globalenv &lt;br /&gt;#gd = importr('grDevices') &lt;br /&gt;dim = r['dim'] &lt;br /&gt;&lt;br /&gt;r('data("sample.ExpressionSet")') &lt;br /&gt;sample_ExpressionSet = r['sample.ExpressionSet'] &lt;br /&gt;eset = sample_ExpressionSet &lt;br /&gt;#print tuple(ri.globalenv) &lt;br /&gt;print eset &lt;br /&gt;&lt;br /&gt;print dim(eset) &lt;br /&gt;ed = eset.exprs &lt;br /&gt;print ed.rx(1,1) &lt;br /&gt;&lt;br /&gt;# no way to do es[x,y] from Python? &lt;br /&gt;# just wrap it &lt;br /&gt;r(''' &lt;br /&gt;do_sel &lt;-function(obj,sel,bycol=FALSE) {&lt;br /&gt;if (bycol) { return(obj[,sel]) } &lt;br /&gt;else { return(obj[sel,]) } &lt;br /&gt;} &lt;br /&gt;''') &lt;br /&gt;&lt;br /&gt;do_sel = r['do_sel'] &lt;br /&gt;# both work: &lt;br /&gt;v = robjects.IntVector([2,3,6]) &lt;br /&gt;v = robjects.BoolVector([True,False]*13) &lt;br /&gt;eset_sub = do_sel(eset,v,bycol=True) &lt;br /&gt;eset_sub = do_sel(eset_sub,v) &lt;br /&gt;print dim(eset_sub) &lt;br /&gt;&lt;br /&gt;# no explicit featureData, just from data rows &lt;br /&gt;rownames = r['rownames'] &lt;br /&gt;fd = rownames(ed) &lt;br /&gt;print fd[:2] &lt;br /&gt;&lt;br /&gt;# get the gene names &lt;br /&gt;importr('annaffy') &lt;br /&gt;r(''' &lt;br /&gt;get.genenames &lt;- function(probeids) {&lt;br /&gt;symbols &lt;- aafSymbol(probeids, 'hgu95av2') &lt;br /&gt;getText(symbols) } &lt;br /&gt;''') &lt;br /&gt;get_genenames = r['get.genenames'] &lt;br /&gt;gn = get_genenames(fd) &lt;br /&gt;&lt;br /&gt;# slightly fancy, no dups, original order &lt;br /&gt;from collections import OrderedDict &lt;br /&gt;z = zip(gn,[None]*len(gn)) &lt;br /&gt;D = OrderedDict(z) &lt;br /&gt;L = D.keys() &lt;br /&gt;for i in range(4):  print L[i*5:i*5+5] &lt;br /&gt;print &lt;br /&gt;&lt;br /&gt;pd = eset.do_slot('phenoData') &lt;br /&gt;data = pd.do_slot('data') &lt;br /&gt;v = robjects.IntVector(range(1,4)) &lt;br /&gt;print do_sel(data,v) &lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;pre&gt;&gt; python script.py &lt;br /&gt;ExpressionSet (storageMode: lockedEnvironment) &lt;br /&gt;assayData: 500 features, 26 samples  &lt;br /&gt;element names: exprs, se.exprs  &lt;br /&gt;protocolData: none &lt;br /&gt;phenoData &lt;br /&gt;sampleNames: A B ... Z (26 total) &lt;br /&gt;varLabels: sex type score &lt;br /&gt;varMetadata: labelDescription &lt;br /&gt;featureData: none &lt;br /&gt;experimentData: use 'experimentData(object)' &lt;br /&gt;Annotation: hgu95av2  &lt;br /&gt;&lt;br /&gt;Features  Samples  &lt;br /&gt;500       26  &lt;br /&gt;&lt;br /&gt;[1] 192.742 &lt;br /&gt;&lt;br /&gt;Features  Samples  &lt;br /&gt;3        3  &lt;br /&gt;&lt;br /&gt;[1] "AFFX-MurIL2_at"  "AFFX-MurIL10_at" &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;******* Deprecation warning *******: &lt;br /&gt;&lt;br /&gt;The package 'hgu95av2' is deprecated and will not be supported in the future.  &lt;br /&gt;&lt;br /&gt;Instead we strongly reccomend that you should start using the 'hgu95av2.db' package.  &lt;br /&gt;&lt;br /&gt;We hope you will enjoy these new packages.  If you still have questions, you can search  &lt;br /&gt;(http://dir.gmane.org/gmane.science.biology.informatics.conductor) or ask the mailing list  &lt;br /&gt;(http://bioconductor.org/docs/mailList.html).   &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Loading required package: hgu95av2 &lt;br /&gt;['', 'STAT1', 'GAPDH', 'ACTB', 'TFRC'] &lt;br /&gt;['C15orf31', 'ACTL6B', 'GLRA1', 'KCNB2', 'MGAT5'] &lt;br /&gt;['BMP3', 'RPL14', 'ZCWPW2', 'KITLG', 'GPR12'] &lt;br /&gt;['TRA@', 'ATP8A2', 'C1orf68', 'FAM20B', 'SLC34A1'] &lt;br /&gt;&lt;br /&gt;sex    type score &lt;br /&gt;A Female Control  0.75 &lt;br /&gt;B   Male    Case  0.40 &lt;br /&gt;C   Male Control  0.73 &lt;br /&gt;&lt;br /&gt;&gt;  &lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-4609803609173593906?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/4609803609173593906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=4609803609173593906' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4609803609173593906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4609803609173593906'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/bioonductor-summary.html' title='Bioonductor:  summary'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8241173552630252993</id><published>2011-08-19T19:26:00.009-04:00</published><updated>2011-08-20T06:46:19.889-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RPy2'/><category scheme='http://www.blogger.com/atom/ns#' term='Bioconductor'/><title type='text'>Bioconductor:  multiple plots</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-pcSUX-S7el8/Tk-OxMyRA3I/AAAAAAAABv8/0bGsdnMYAXI/s1600/ALL1-AF4_NEG.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://3.bp.blogspot.com/-pcSUX-S7el8/Tk-OxMyRA3I/AAAAAAAABv8/0bGsdnMYAXI/s320/ALL1-AF4_NEG.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5642885834015310706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Actually, I have a bit more to do with Bioconductor ExpressionSets, as long as I'm thinking about it.  When I first played with the ALL example, I tried other pairs besides ('ALL1/AF4','BCR/ABL')---I'd have to look now, but they are probably in the original paper too.  Anyway, in the first talk I gave about this stuff, I made plots of all the pairs.  Some are really nice.  So that's what I'd like to show now.  &lt;br /&gt;&lt;br /&gt;The difference is that then, I wrote the code in R, and I did not like the experience.&lt;br /&gt;&lt;br /&gt;In Python, we do the standard imports.  We factor out the R code into several functions, then load it from a text file in Python, and execute the code in R-space.  In Python, we pick pairs to compare and call a plotting function in R.&lt;br /&gt;&lt;br /&gt;The R code is a little hackish (I'm thinking of color.map), but this is a good start.&lt;br /&gt;&lt;br /&gt;R code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;color.map &lt;- function(g) {&lt;br /&gt;  colors = c('red','green','blue',&lt;br /&gt;    'cyan','magenta','maroon')&lt;br /&gt;  if (g == 'ALL1/AF4') i=1&lt;br /&gt;  if (g == 'BCR/ABL') i=2&lt;br /&gt;  if (g == 'E2A/PBX1') i=3&lt;br /&gt;  if (g == 'NEG') i=4&lt;br /&gt;  if (g == 'NUP-98') i=5&lt;br /&gt;  if (g == 'p15/p16') i=6&lt;br /&gt;  colors[i]&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;library('limma')&lt;br /&gt;library('annaffy')&lt;br /&gt;&lt;br /&gt;get.genenames &lt;- function(eset) {&lt;br /&gt;  probeids &lt;- featureNames(eset) &lt;br /&gt;  symbols &lt;- aafSymbol(probeids, 'hgu95av2') &lt;br /&gt;  getText(symbols)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;compare.factors &lt;- function(eset,L) {&lt;br /&gt;  eset.sub = eset[,eset$mol.biol %in% L]&lt;br /&gt;  f &lt;- factor(as.character(eset.sub$mol.biol))&lt;br /&gt;  design &lt;- model.matrix(~f)&lt;br /&gt;  fit &lt;- eBayes(lmFit(eset.sub,design))&lt;br /&gt;  pv = fit$p.value[,2]&lt;br /&gt;  sel &lt;- p.adjust(pv) &lt; 0.001&lt;br /&gt;  eset.sel &lt;- eset.sub[sel,]&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;plot.eset &lt;-function(eset,...) {&lt;br /&gt;  patient.colors &lt;- unlist(lapply(&lt;br /&gt;    eset$mol.biol,color.map))&lt;br /&gt;  genenames = get.genenames(eset)&lt;br /&gt;  heatmap(exprs(eset),&lt;br /&gt;    col=topo.colors(100),&lt;br /&gt;    ColSideColors=patient.colors,&lt;br /&gt;    labRow=genenames)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The R code is in a file &lt;code&gt;Rcode.txt&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Python code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import rpy2.robjects as robjects&lt;br /&gt;from rpy2.robjects.packages import importr &lt;br /&gt;import bioc.biobase as biobase&lt;br /&gt;&lt;br /&gt;r = robjects.r&lt;br /&gt;g = robjects.globalenv&lt;br /&gt;gd = importr('grDevices')&lt;br /&gt;&lt;br /&gt;importr('ALL')&lt;br /&gt;r('data("ALL")')&lt;br /&gt;ALL = g['ALL']&lt;br /&gt;eset = biobase.ExpressionSet(ALL)&lt;br /&gt;#--------------------------------------------&lt;br /&gt;&lt;br /&gt;FH = open('Rcode.txt','r')&lt;br /&gt;s = FH.read()&lt;br /&gt;FH.close()&lt;br /&gt;r(s)&lt;br /&gt;compare_factors = r['compare.factors']&lt;br /&gt;plot_eset = r['plot.eset']&lt;br /&gt;#--------------------------------------------&lt;br /&gt;targets = [ ['ALL1/AF4','NEG'],&lt;br /&gt;            ['ALL1/AF4','BCR/ABL'],&lt;br /&gt;            ['E2A/PBX1','BCR/ABL'] ]&lt;br /&gt;&lt;br /&gt;def get_ofn(t):&lt;br /&gt;    #print t, len(t)&lt;br /&gt;    u,v = t&lt;br /&gt;    s = u + '_' + v&lt;br /&gt;    ofn = s.replace('/','-') + '.pdf'&lt;br /&gt;    return ofn&lt;br /&gt;    &lt;br /&gt;def plot(eset_sub,t):&lt;br /&gt;    ofn = get_ofn(t)&lt;br /&gt;    gd.pdf(ofn)&lt;br /&gt;    plot_eset(eset_sub,ofn)&lt;br /&gt;    gd.dev_off()&lt;br /&gt;               &lt;br /&gt;for t in targets:&lt;br /&gt;    eset_sub = compare_factors(eset,t)&lt;br /&gt;    plot(eset_sub,t)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first plot is at the top, and the second and third are below.  It's pretty clear that there are significant commonalities according to mol.biol.  BTW, I adjusted the target p-value to keep the number of hits down.&lt;br /&gt;&lt;br /&gt;I also added code to substitute the gene names in the plots.  That's pretty cool.&lt;br /&gt;&lt;br /&gt;And I have to figure out what to do about code listings.  &amp;lt;pre&gt; looks good in preview, but we get the extra newlines;  &amp;lt;code&gt; doesn't give the right spacings, but it doesn't have the double newlines.  I decided to go with &amp;lt;pre&gt; today.&lt;br /&gt;&lt;br /&gt;There are problems with the &lt;a href="http://telliott99.blogspot.com/2011/08/test_14.html"&gt;alternatives&lt;/a&gt;.  That's for another time.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-56JPBKJQIng/Tk-OwvF-SEI/AAAAAAAABvs/mup2GmlKVIM/s1600/ALL1-AF4_BCR-ABL.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://2.bp.blogspot.com/-56JPBKJQIng/Tk-OwvF-SEI/AAAAAAAABvs/mup2GmlKVIM/s320/ALL1-AF4_BCR-ABL.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5642885826044905538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-EaHsTpq4coo/Tk-Ow1OyxsI/AAAAAAAABv0/aVCnk3gRqes/s1600/E2A-PBX1_BCR-ABL.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://3.bp.blogspot.com/-EaHsTpq4coo/Tk-Ow1OyxsI/AAAAAAAABv0/aVCnk3gRqes/s320/E2A-PBX1_BCR-ABL.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5642885827692512962" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8241173552630252993?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8241173552630252993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8241173552630252993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8241173552630252993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8241173552630252993'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/bioconductor-multiple-plots.html' title='Bioconductor:  multiple plots'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-pcSUX-S7el8/Tk-OxMyRA3I/AAAAAAAABv8/0bGsdnMYAXI/s72-c/ALL1-AF4_NEG.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7287510399379621070</id><published>2011-08-19T15:13:00.003-04:00</published><updated>2011-08-19T20:32:10.042-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RPy2'/><category scheme='http://www.blogger.com/atom/ns#' term='Bioconductor'/><title type='text'>Learning to use RPy2 (5)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;Here is the result of my experiment with the &lt;a href="http://pypi.python.org/pypi/rpy2-bioconductor-extensions"&gt;rpy2-bioconductor-extensions-0.2&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import rpy2.robjects as robjects&lt;br /&gt;from rpy2.robjects.packages import importr &lt;br /&gt;import bioc.biobase as biobase&lt;br /&gt;r = robjects.r&lt;br /&gt;g = robjects.globalenv&lt;br /&gt;&lt;br /&gt;importr('ALL')&lt;br /&gt;r('data("ALL")')&lt;br /&gt;data = g['ALL']&lt;br /&gt;eset = biobase.ExpressionSet(data)&lt;br /&gt;print eset&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Run as a script.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; python script.py&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;First (above) section output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ExpressionSet (storageMode: lockedEnvironment)&lt;br /&gt;assayData: 12625 features, 128 samples &lt;br /&gt;  element names: exprs &lt;br /&gt;protocolData: none&lt;br /&gt;phenoData&lt;br /&gt;  sampleNames: 01005 01010 ... LAL4 (128 total)&lt;br /&gt;  varLabels: cod diagnosis ... date last seen (21 total)&lt;br /&gt;  varMetadata: labelDescription&lt;br /&gt;featureData: none&lt;br /&gt;experimentData: use 'experimentData(object)'&lt;br /&gt;  pubMedIds: 14684422 16243790 &lt;br /&gt;Annotation: hgu95av2 &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Part 2:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;expr_data = eset.exprs&lt;br /&gt;print len(expr_data)&lt;br /&gt;L = tuple(expr_data[:5])&lt;br /&gt;print [round(t,3) for t in L]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;1616000&lt;br /&gt;[7.597, 5.046, 3.9, 5.904, 5.925]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Part 3:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;print list(eset.slotnames())&lt;br /&gt;phenoData = eset.do_slot('phenoData')&lt;br /&gt;print 'phenoData', id(phenoData)&lt;br /&gt;print phenoData&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;['experimentData', 'assayData', 'phenoData', 'featureData', 'annotation', 'protocolData', '.__classVersion__']&lt;br /&gt;phenoData  0x10bbc35a8&lt;br /&gt;An object of class "AnnotatedDataFrame"&lt;br /&gt;  sampleNames: 01005 01010 ... LAL4 (128 total)&lt;br /&gt;  varLabels: cod diagnosis ... date last seen (21 total)&lt;br /&gt;  varMetadata: labelDescription&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Part 4:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;pd = eset.get_phenodata()&lt;br /&gt;print 'pd', id(pd)&lt;br /&gt;print pd&lt;br /&gt;print list(pd.slotnames())&lt;br /&gt;print&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;pd 0x10bbc3488&lt;br /&gt;An object of class "AnnotatedDataFrame"&lt;br /&gt;  sampleNames: 01005 01010 ... LAL4 (128 total)&lt;br /&gt;  varLabels: cod diagnosis ... date last seen (21 total)&lt;br /&gt;  varMetadata: labelDescription&lt;br /&gt;&lt;br /&gt;['varMetadata', 'data', 'dimLabels', '.__classVersion__']&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Part 5:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;data = pd.do_slot('data')&lt;br /&gt;print 'data'&lt;br /&gt;print type(data)&lt;br /&gt;mb = pd.pdata.rx2('mol.biol')&lt;br /&gt;print list(mb)[:10]&lt;br /&gt;levels = r['levels']&lt;br /&gt;print levels(mb)&lt;br /&gt;print list(data.rx2('mol.biol'))[:10]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;data&lt;br /&gt;&amp;lt;class 'rpy2.robjects.vectors.DataFrame'&gt;&lt;br /&gt;[2, 4, 2, 1, 4, 4, 4, 4, 4, 2]&lt;br /&gt;[1] "ALL1/AF4" "BCR/ABL"  "E2A/PBX1" "NEG"      "NUP-98"   "p15/p16" &lt;br /&gt;&lt;br /&gt;[2, 4, 2, 1, 4, 4, 4, 4, 4, 2]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Part 6:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;fd = eset.get_featuredata&lt;br /&gt;print fd&lt;br /&gt;# fd() gives AttributeError, no _featureData&lt;br /&gt;# &lt;br /&gt;featureNames = robjects.r['featureNames']&lt;br /&gt;fn = featureNames(eset)&lt;br /&gt;print len(fn), fn[0]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;output:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;bound method ExpressionSet.get_featuredata of &lt;ExpressionSet - Python:0x10c897e60 / R:0x7fe7253b0070&gt;&gt;&lt;br /&gt;12625 1000_at&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;In the last part, the "new" way doesn't seem to work yet.  So I did as before.&lt;br /&gt;Well, that's it for Bioconductor and Rpy2 for now.  The presentation could be a lot better organized, but at least we figured out how to do most things.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7287510399379621070?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7287510399379621070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7287510399379621070' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7287510399379621070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7287510399379621070'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/learning-to-use-rpy2-5.html' title='Learning to use RPy2 (5)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-6833590695297507159</id><published>2011-08-19T08:00:00.002-04:00</published><updated>2011-08-19T15:35:53.332-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RPy2'/><title type='text'>Learning to use RPy2 (4)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;This is a brief post about how to access the components (attributes) of S3 and S4 classes from R, using RPy2.  Just a few notes on what I've found, but YMMV, of course.  There's a pretty detailed post about this kind of thing &lt;a href="http://abhishek-tiwari.com/2011/01/class-and-objects-in-r-s3-style.html"&gt;here&lt;/a&gt;.  And of course, the R documentation is extensive (but more complex).&lt;br /&gt;&lt;br /&gt;Note:  the Bioconductor classes can be handled by using &lt;a href="http://packages.python.org/rpy2-bioconductor-extensions/"&gt;extensions&lt;/a&gt; to RPy2.  That's for a later post.  First some standard imports and a bit of setup:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; import rpy2.robjects as robjects &lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects.packages import importr &lt;br /&gt;&gt;&gt;&gt; r = robjects.r &lt;br /&gt;&gt;&gt;&gt; g = robjects.globalenv &lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We define a toy S3 class starting from a vector, simply by giving it the "class" attribute, and then define a version of print that can work on it:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; r('''&lt;br /&gt;... x &lt;- rep(0:1, c(3,6))&lt;br /&gt;... myS3_class &lt;- x&lt;br /&gt;... class(myS3_class) &lt;- 'myS3_class'&lt;br /&gt;... print.myS3_class &lt;- function(x, ...) {&lt;br /&gt;...   cat("This is my vector:\n")&lt;br /&gt;...   cat(paste(x[1:5]), "...\n")&lt;br /&gt;... }&lt;br /&gt;... ''')&lt;br /&gt;&amp;lt;SignatureTranslatedFunction - Python:0x1446648 / R:0xc5bf34&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; myS3_class = r['myS3_class']&lt;br /&gt;&gt;&gt;&gt; myS3_class.rclass&lt;br /&gt;&amp;lt;rpy2.rinterface.SexpVector - Python:0x194550 / R:0x2c51048&gt;&lt;br /&gt;&gt;&gt;&gt; myS3_class.r_repr()&lt;br /&gt;'structure(c(0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L), class = "myS3_class")'&lt;br /&gt;&gt;&gt;&gt; attributes = r['attributes']&lt;br /&gt;&gt;&gt;&gt; aL = attributes(myS3_class)&lt;br /&gt;&gt;&gt;&gt; type(aL)&lt;br /&gt;&amp;lt;class 'rpy2.robjects.vectors.ListVector'&gt;&lt;br /&gt;&gt;&gt;&gt; aL.rx2('class')&lt;br /&gt;&amp;lt;StrVector - Python:0x23b00a8 / R:0x2c51048&gt;&lt;br /&gt;['myS3_class']&lt;br /&gt;&gt;&gt;&gt; len(aL)&lt;br /&gt;1&lt;br /&gt;&gt;&gt;&gt; aL.rx2('structure')&lt;br /&gt;rpy2.rinterface.NULL&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;To get at the actual numeric data:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; len(myS3_class)&lt;br /&gt;9&lt;br /&gt;&gt;&gt;&gt; v = r('as.integer(myS3_class)')&lt;br /&gt;&gt;&gt;&gt; v&lt;br /&gt;&amp;lt;IntVector - Python:0x23b0fa8 / R:0xb77c80&gt;&lt;br /&gt;[       0,        0,        0, ...,        1,        1,        1]&lt;br /&gt;&gt;&gt;&gt; structure = r['structure']&lt;br /&gt;&gt;&gt;&gt; structure(myS3_class)&lt;br /&gt;&amp;lt;IntVector - Python:0x23b71e8 / R:0x2864a00&gt;&lt;br /&gt;[       0,        0,        0, ...,        1,        1,        1]&lt;br /&gt;&gt;&gt;&gt; tuple(myS3_class)&lt;br /&gt;(0, 0, 0, 1, 1, 1, 1, 1, 1)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now, look at symbols in the global "environment":&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; import rpy2.rinterface as ri&lt;br /&gt;&gt;&gt;&gt; tuple(ri.globalenv)&lt;br /&gt;('myS3_class', 'print.myS3_class', 'x')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Let's try a simple S4 class:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; r('''&lt;br /&gt;... setClass(&lt;br /&gt;...   Class="myS4_class",&lt;br /&gt;...   representation=representation(&lt;br /&gt;...     times = "numeric",&lt;br /&gt;...     names = "character"&lt;br /&gt;...   )&lt;br /&gt;... )&lt;br /&gt;... ''')&lt;br /&gt;&amp;lt;StrVector - Python:0x23b0af8 / R:0xdc3068&gt;&lt;br /&gt;['myS4_class']&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and instantiate one of them:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; r('''&lt;br /&gt;... myS4_class = new(&lt;br /&gt;...   Class="myS4_class", &lt;br /&gt;...   times=c(1,2,4),&lt;br /&gt;...   names=c('a','b')&lt;br /&gt;... )&lt;br /&gt;... ''')&lt;br /&gt;&amp;lt;RS4 - Python:0x23b0ad0 / R:0xa4d550&gt;&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now, to access its slots:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; myS4_class = r['myS4_class']&lt;br /&gt;&gt;&gt;&gt; slotNames = r['slotNames']&lt;br /&gt;&gt;&gt;&gt; slotNames(myS4_class)&lt;br /&gt;&amp;lt;StrVector - Python:0x23b0a58 / R:0xae3de8&gt;&lt;br /&gt;['times', 'names']&lt;br /&gt;&gt;&gt;&gt; myS4_class.do_slot('times')&lt;br /&gt;&amp;lt;FloatVector - Python:0x23b0ad0 / R:0x2c755b8&gt;&lt;br /&gt;[1.000000, 2.000000, 4.000000]&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Assign to one:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; v = robjects.StrVector('abcde')&lt;br /&gt;&gt;&gt;&gt; myS4_class.do_slot_assign('names', v)&lt;br /&gt;&gt;&gt;&gt; print(myS4_class)&lt;br /&gt;An object of class "myS4_class"&lt;br /&gt;Slot "times":&lt;br /&gt;[1] 1 2 4&lt;br /&gt;&lt;br /&gt;Slot "names":&lt;br /&gt;[1] "a" "b" "c" "d" "e"&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; v = myS4_class.do_slot('names')&lt;br /&gt;&gt;&gt;&gt; v&lt;br /&gt;&lt;StrVector - Python:0x23b0d78 / R:0x2c753c0&gt;&lt;br /&gt;['a', 'b', 'c', 'd', 'e']&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That's it for this example.&lt;br /&gt;&lt;/span&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;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-6833590695297507159?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/6833590695297507159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=6833590695297507159' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6833590695297507159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6833590695297507159'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/learning-to-use-rpy2-module-4.html' title='Learning to use RPy2 (4)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7375805762173992989</id><published>2011-08-18T22:31:00.006-04:00</published><updated>2011-08-19T15:36:42.177-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RPy2'/><category scheme='http://www.blogger.com/atom/ns#' term='Bioconductor'/><title type='text'>Learning to use RPy2 (3)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-u_ZkTf_kf14/Tk3OSotVzJI/AAAAAAAABvM/AEyuDWClDEk/s1600/Screen%2BShot%2B2011-08-18%2Bat%2B10.43.04%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 264px;" src="http://3.bp.blogspot.com/-u_ZkTf_kf14/Tk3OSotVzJI/AAAAAAAABvM/AEyuDWClDEk/s320/Screen%2BShot%2B2011-08-18%2Bat%2B10.43.04%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5642392727725657234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;So, I'd been thinking that I'd do the Bioconductor &lt;a href="http://telliott99.blogspot.com/2011/08/first-heat-map-using-bioconductor.html"&gt;example&lt;/a&gt; in Python.  The first group of commands in R is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;library('ALL') &lt;br /&gt;data('ALL') &lt;br /&gt;library('limma') &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;In Python we do:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; import rpy2.robjects as robjects&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects.packages import importr&lt;br /&gt;&gt;&gt;&gt; ALL = importr('ALL')&lt;br /&gt;&gt;&gt;&gt; limma = importr('limma')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and to get the data, we can (cheat a bit and) do&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; robjects.r('data("ALL")')&lt;br /&gt;&amp;lt;StrVector - Python:0x10eb15a28 / R:0x7f8371183f38&gt;&lt;br /&gt;['ALL']&lt;br /&gt;&gt;&gt;&gt; data = robjects.globalenv['ALL']&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The second group of R commands is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;eset &lt;- ALL[,ALL$mol.biol %in% c('BCR/ABL','ALL1/AF4')] &lt;br /&gt;f &lt;- factor(as.character(eset$mol.biol)) &lt;br /&gt;design &lt;- model.matrix(~f) &lt;br /&gt;fit &lt;- eBayes(lmFit(eset,design)) &lt;br /&gt;sel &lt;- p.adjust(fit$p.value[,2]) &lt; 0.05 &lt;br /&gt;esetSel &lt;- eset[sel,]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;I figured out how to take apart the data object above, and implement the first line.  That was enough to convince me that it's not worth it.  &lt;br /&gt;&lt;br /&gt;I realized now that the use case is to get the underlying data into and back out of Python.  That is, eventually we'll want to learn about how to construct an ExpressionSet object with data starting in Python data structures.  But first:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; featureNames = robjects.r['featureNames']&lt;br /&gt;&gt;&gt;&gt; fn = featureNames(data)&lt;br /&gt;&gt;&gt;&gt; len(fn)&lt;br /&gt;12625&lt;br /&gt;&gt;&gt;&gt; fn[:5]&lt;br /&gt;&amp;lt;StrVector - Python:0x10eb19ef0 / R:0x7f8371eba940&gt;&lt;br /&gt;['1000_at', '1001_at', '1002_f..., '1003_s..., '1004_at']&lt;br /&gt;&gt;&gt;&gt; fn.rx(1)&lt;br /&gt;&amp;lt;StrVector - Python:0x10eb19440 / R:0x7f8371f85208&gt;&lt;br /&gt;['1000_at']&lt;br /&gt;&gt;&gt;&gt; tuple(fn[:4])&lt;br /&gt;('1000_at', '1001_at', '1002_f_at', '1003_s_at')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That's what we'll want.&lt;br /&gt;&lt;br /&gt;The expression data:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; exprs = robjects.r['exprs'] &lt;br /&gt;&gt;&gt;&gt; ed = exprs(data)&lt;br /&gt;&gt;&gt;&gt; ed&lt;br /&gt;&amp;lt;Matrix - Python:0x10eb10710 / R:0x1137e6000&gt;&lt;br /&gt;[7.597323, 5.046194, 3.900466, ..., 3.095670, 3.342961, 3.842535]&lt;br /&gt;&gt;&gt;&gt; dim = robjects.r['dim']&lt;br /&gt;&gt;&gt;&gt; dim(ed)&lt;br /&gt;&amp;lt;IntVector - Python:0x10eb19cb0 / R:0x7f8372023548&gt;&lt;br /&gt;[   12625,      128]&lt;br /&gt;&gt;&gt;&gt; t = tuple(ed)&lt;br /&gt;&gt;&gt;&gt; t[:2]&lt;br /&gt;(7.597322981163869, 5.046194285620063)&lt;br /&gt;&gt;&gt;&gt; len(t)&lt;br /&gt;1616000&lt;br /&gt;&gt;&gt;&gt; import numpy as np&lt;br /&gt;&gt;&gt;&gt; A = np.array(list(t))&lt;br /&gt;&gt;&gt;&gt; A.shape = tuple(dim(ed))&lt;br /&gt;&gt;&gt;&gt; A.shape&lt;br /&gt;(12625, 128)&lt;br /&gt;&gt;&gt;&gt; A[:5,:3]&lt;br /&gt;array([[ 7.59732298,  5.04619429,  3.90046642],&lt;br /&gt;       [ 5.20211564,  5.81351983,  5.81160593],&lt;br /&gt;       [ 6.14364259,  7.1470674 ,  6.77438247],&lt;br /&gt;       [ 6.76609498,  4.61191719,  4.91830898],&lt;br /&gt;       [ 7.12201406,  7.61231255,  6.82803053]])&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The phenotypic data including &lt;code&gt;mol.biol&lt;/code&gt;:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; phenoData = robjects.r['phenoData']&lt;br /&gt;&gt;&gt;&gt; pd = phenoData(data)&lt;br /&gt;&gt;&gt;&gt; mb = pd.rx2('mol.biol') &lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "&lt;stdin&gt;", line 1, in &lt;module&gt;&lt;br /&gt;AttributeError: 'RS4' object has no attribute 'rx2'&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;UPDATE:  this way&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; slotNames = r['slotNames']&lt;br /&gt;&gt;&gt;&gt; phenoData = r['phenoData']&lt;br /&gt;&gt;&gt;&gt; pd = phenoData(ALL)&lt;br /&gt;&gt;&gt;&gt; slotNames(pd)&lt;br /&gt;&amp;lt;StrVector - Python:0x1023f77a0 / R:0x103140528&gt;&lt;br /&gt;['varMetada..., 'data', 'dimLabels', '.__classV...]&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; df = pd.do_slot("data")&lt;br /&gt;&gt;&gt;&gt; df.rx2('sex')&lt;br /&gt;&amp;lt;FactorVector - Python:0x1023e2170 / R:0x10268da40&gt;&lt;br /&gt;[       2,        2,        1, ...,        2,        2, NA_integer_]&lt;br /&gt;&gt;&gt;&gt; mb = df.rx2('mol.biol')&lt;br /&gt;&gt;&gt;&gt; levels(mb)&lt;br /&gt;&amp;lt;StrVector - Python:0x1023e2ea8 / R:0x103742d88&gt;&lt;br /&gt;['ALL1..., 'BCR/..., 'E2A/..., 'NEG', 'NUP-..., 'p15/...]&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;pData works:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; pData = robjects.r['pData']&lt;br /&gt;&gt;&gt;&gt; pd = pData(data)&lt;br /&gt;&gt;&gt;&gt; mb = pd.rx2('mol.biol') &lt;br /&gt;&gt;&gt;&gt; mb&lt;br /&gt;&amp;lt;FactorVector - Python:0x1154c5cf8 / R:0x7f8374e72010&gt;&lt;br /&gt;[       2,        4,        2, ...,        4,        4,        4]&lt;br /&gt;&gt;&gt;&gt; len(mb)&lt;br /&gt;128&lt;br /&gt;&gt;&gt;&gt; mb.levels&lt;br /&gt;&amp;lt;StrVector - Python:0x1154c5f38 / R:0x7f8371a5c660&gt;&lt;br /&gt;['ALL1..., 'BCR/..., 'E2A/..., 'NEG', 'NUP-..., 'p15/...]&lt;br /&gt;&gt;&gt;&gt; L = list(mb)&lt;br /&gt;&gt;&gt;&gt; L[:5]&lt;br /&gt;[2, 4, 2, 1, 4]&lt;br /&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Notice how the factor changed into ints (see the Rpy2 &lt;a href="http://rpy.sourceforge.net/rpy2/doc-2.2/html/vector.html#factorvector"&gt;docs&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Now, to select the entries we want:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; i = mb.levels.index('ALL1/AF4') + 1&lt;br /&gt;&gt;&gt;&gt; j = mb.levels.index('BCR/ABL') + 1&lt;br /&gt;&gt;&gt;&gt; L = [True if e in [i,j] else False for e in L]&lt;br /&gt;&gt;&gt;&gt; sum(L)&lt;br /&gt;47&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects import BoolVector&lt;br /&gt;&gt;&gt;&gt; bv = BoolVector(L)&lt;br /&gt;&gt;&gt;&gt; robjects.r('f &lt;- function(e,bv) { e[,bv] }')&lt;br /&gt;&amp;lt;SignatureTranslatedFunction - Python:0x1154cf2d8 / R:0x7f8371fa4400&gt;&lt;br /&gt;&gt;&gt;&gt; f = robjects.r['f']&lt;br /&gt;&gt;&gt;&gt; eset = f(data,bv)&lt;br /&gt;&gt;&gt;&gt; dim(eset)&lt;br /&gt;&amp;lt;IntVector - Python:0x1154cf638 / R:0x7f8375052c68&gt;&lt;br /&gt;[   12625,       47]&lt;br /&gt;&gt;&gt;&gt; eset.rclass&lt;br /&gt;&amp;lt;rpy2.rinterface.SexpVector - Python:0x10eb17ee8 / R:0x7f83750f5698&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And that's what we set out to do.&lt;br /&gt;&lt;br /&gt;Constructing an R object from data in Python will have to wait.&lt;br /&gt;&lt;br /&gt;Another look at the selected data:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; t = tuple(exprs(eset))&lt;br /&gt;&gt;&gt;&gt; A = np.array(list(t))&lt;br /&gt;&gt;&gt;&gt; A.shape = tuple(dim(eset))&lt;br /&gt;&gt;&gt;&gt; A.shape&lt;br /&gt;(12625, 47)&lt;br /&gt;&gt;&gt;&gt; B = A[:100,]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Might as well plot something while we're here:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; fig = plt.figure()&lt;br /&gt;&gt;&gt;&gt; plt.hot()&lt;br /&gt;&gt;&gt;&gt; plt.pcolormesh(B)&lt;br /&gt;&amp;lt;matplotlib.collections.QuadMesh object at 0x10d727610&gt;&lt;br /&gt;&gt;&gt;&gt; plt.colorbar() &lt;br /&gt;&amp;lt;matplotlib.colorbar.Colorbar instance at 0x10d707560&gt;&lt;br /&gt;&gt;&gt;&gt; plt.savefig('example.png')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That is what is at the top of the post.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7375805762173992989?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7375805762173992989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7375805762173992989' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7375805762173992989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7375805762173992989'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/learning-to-use-rpy2-3.html' title='Learning to use RPy2 (3)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-u_ZkTf_kf14/Tk3OSotVzJI/AAAAAAAABvM/AEyuDWClDEk/s72-c/Screen%2BShot%2B2011-08-18%2Bat%2B10.43.04%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-767329439316554107</id><published>2011-08-18T16:06:00.005-04:00</published><updated>2011-08-18T21:30:22.025-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RPy2'/><title type='text'>Learning to use RPy2 (2)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-3utQZ8FX1NA/Tk12j-Y7HjI/AAAAAAAABvE/lavoLFlJnr4/s1600/Screen%2Bshot%2B2011-08-18%2Bat%2B4.26.38%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 312px;" src="http://2.bp.blogspot.com/-3utQZ8FX1NA/Tk12j-Y7HjI/AAAAAAAABvE/lavoLFlJnr4/s320/Screen%2Bshot%2B2011-08-18%2Bat%2B4.26.38%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5642296268580134450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;We're working on &lt;a href="http://rpy.sourceforge.net/rpy2.html"&gt;RPy2&lt;/a&gt;.  Before I continue with Bioconductor, we should work through more of the examples in the docs.&lt;br /&gt;&lt;br /&gt;I rashly asked a &lt;a href="http://stackoverflow.com/questions/7105876/rpy2-and-bioconductor-gene-expression-example/7113076#7113076"&gt;question&lt;/a&gt; on Stack Overflow this morning (after being stumped for several hours), then stumbled across the answer.  The question is, how to load the &lt;i&gt;data&lt;/i&gt; from &lt;code&gt;ALL&lt;/code&gt;.  In R we would just do:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;data('ALL')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and then the objects would be available to us through their names.  It turns out that in Python it is almost that simple.  I had actually seen the answer, which is a kind of "shortcut" in which we just execute R code directly, and then grab a variable through the name assigned in R.  (I used this device several times in the previous &lt;a href="http://telliott99.blogspot.com/2011/08/test_18.html"&gt;post&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;(And I should note that there is apparently a more elegant solution in the &lt;a href="http://pypi.python.org/pypi/rpy2-bioconductor-extensions"&gt;bioconductor extensions to rpy2&lt;/a&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; import rpy2.robjects as robjects&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects.packages import importr&lt;br /&gt;&gt;&gt;&gt; base =  importr('base')&lt;br /&gt;&gt;&gt;&gt; ALL = importr('ALL')&lt;br /&gt;&gt;&gt;&gt; data = robjects.r('data(ALL)')&lt;br /&gt;&gt;&gt;&gt; data.rclass&lt;br /&gt;&amp;lt;rpy2.rinterface.SexpVector - Python:0x258b190 / R:0xdf86c8&gt;&lt;br /&gt;&gt;&gt;&gt; data = robjects.globalenv['ALL']&lt;br /&gt;&gt;&gt;&gt; data&lt;br /&gt;&amp;lt;RS4 - Python:0x2591490 / R:0x29a2134&gt;&lt;br /&gt;&gt;&gt;&gt; data.rclass&lt;br /&gt;&amp;lt;rpy2.rinterface.SexpVector - Python:0x258b3b0 / R:0xdf85c8&gt;&lt;br /&gt;&gt;&gt;&gt; featureNames = robjects.r('featureNames')&lt;br /&gt;&gt;&gt;&gt; featureNames(data)&lt;br /&gt;&amp;lt;StrVector - Python:0x23e4f08 / R:0x304fc00&gt;&lt;br /&gt;['1000..., '1001..., '1002..., ..., 'AFFX..., 'AFFX..., 'AFFX...]&lt;br /&gt;&gt;&gt;&gt; exprs = robjects.r['exprs']&lt;br /&gt;&gt;&gt;&gt; e = exprs(data)&lt;br /&gt;&gt;&gt;&gt; e&lt;br /&gt;&amp;lt;Matrix - Python:0x23b2da0 / R:0x84d8000&gt;&lt;br /&gt;[7.597323, 5.046194, 3.900466, ..., 3.095670, 3.342961, 3.842535]&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Anyway, we want not to make any more silly mistakes.  Another elementary thing I happened upon in the docs (in &lt;a href="http://rpy.sourceforge.net/rpy2/doc-2.2/html/vector.html#extracting-r-style"&gt;Vectors&lt;/a&gt;) is&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;Access to R-style extracting/subsetting is granted though the two delegators rx and rx2, representing the R functions [ and [[ respectively.&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;It seems to return a strange little beast:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects import r&lt;br /&gt;&gt;&gt;&gt; m = r.matrix(range(4),nrow=2)&lt;br /&gt;&gt;&gt;&gt; value = m.rx(3)&lt;br /&gt;&gt;&gt;&gt; value&lt;br /&gt;&amp;lt;ListVector - Python:0x1023db5a8 / R:0x102cf9c28&gt;&lt;br /&gt;[IntVector]&lt;br /&gt;  &amp;lt;no name&gt;: &lt;class 'rpy2.robjects.vectors.IntVector'&gt;&lt;br /&gt;  &amp;lt;IntVector - Python:0x1023db368 / R:0x102cf99e8&gt;&lt;br /&gt;[       2]&lt;br /&gt;&gt;&gt;&gt; type(value )&lt;br /&gt;&amp;lt;class 'rpy2.robjects.vectors.ListVector'&gt;&lt;br /&gt;&gt;&gt;&gt; value[0]&lt;br /&gt;&amp;lt;IntVector - Python:0x1023db518 / R:0x102cf99e8&gt;&lt;br /&gt;[       2]&lt;br /&gt;&gt;&gt;&gt; value[0][0]&lt;br /&gt;2&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We copy the code to make an R list, directly out of the docs (see &lt;code&gt;?list&lt;/code&gt;):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; r('''e1 &lt;- new.env(); e1$a &lt;- 10; e1$b &lt;- 20; L = as.list(e1)''')&lt;br /&gt;&amp;lt;ListVector - Python:0x1023da4d0 / R:0x103306140&gt;&lt;br /&gt;[FloatVector, FloatVector]&lt;br /&gt;  b: &lt;class 'rpy2.robjects.vectors.FloatVector'&gt;&lt;br /&gt;  &amp;lt;FloatVector - Python:0x1023da680 / R:0x102d1bd58&gt;&lt;br /&gt;[20.000000]&lt;br /&gt;  a: &amp;lt;class 'rpy2.robjects.vectors.FloatVector'&gt;&lt;br /&gt;  &amp;lt;FloatVector - Python:0x1023da3b0 / R:0x102d1bd88&gt;&lt;br /&gt;[10.000000]&lt;br /&gt;&gt;&gt;&gt; L = r['L']&lt;br /&gt;&gt;&gt;&gt; L.rx2('a')&lt;br /&gt;&amp;lt;FloatVector - Python:0x1023da998 / R:0x102d1bd88&gt;&lt;br /&gt;[10.000000]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;Here is a somewhat fancier example involving a linear model (from the &lt;a href="http://rpy.sourceforge.net/rpy2/doc-2.2/html/introduction.html#linear-models"&gt;Intro&lt;/a&gt;).  Look in the docs for the R code.  In Python:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects import FloatVector&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects.packages import importr&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects import globalenv as g&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; stats = importr('stats')&lt;br /&gt;&gt;&gt;&gt; base = importr('base')&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; ctl = FloatVector([4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14])&lt;br /&gt;&gt;&gt;&gt; trt = FloatVector([4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69])&lt;br /&gt;&gt;&gt;&gt; weight = ctl + trt&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; group = base.gl(2, 10, 20, labels = ["Ctl","Trt"])&lt;br /&gt;&gt;&gt;&gt; g["weight"] = weight&lt;br /&gt;&gt;&gt;&gt; g["group"] = group&lt;br /&gt;&gt;&gt;&gt; lm_D9 = stats.lm("weight ~ group")&lt;br /&gt;&gt;&gt;&gt; print(stats.anova(lm_D9))&lt;br /&gt;Analysis of Variance Table&lt;br /&gt;&lt;br /&gt;Response: weight&lt;br /&gt;          Df Sum Sq Mean Sq F value Pr(&gt;F)&lt;br /&gt;group      1 0.6882 0.68820  1.4191  0.249&lt;br /&gt;Residuals 18 8.7292 0.48496&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; print(lm_D9.names)&lt;br /&gt; [1] "coefficients"  "residuals"     "effects"       "rank"         &lt;br /&gt; [5] "fitted.values" "assign"        "qr"            "df.residual"  &lt;br /&gt; [9] "contrasts"     "xlevels"       "call"          "terms"        &lt;br /&gt;[13] "model"        &lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; print names(lm_D9)&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "&amp;lt;stdin&gt;", line 1, in &lt;module&gt;&lt;br /&gt;NameError: name 'names' is not defined&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The next example in this section fails with two errors:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ImportError: cannot import name NA_real.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If we just use zeroes, it fails with &lt;br /&gt;&lt;code&gt;&lt;br /&gt;in __setitem__&lt;br /&gt;    globalenv_ri)&lt;br /&gt;TypeError: All keywords must be strings (or None).&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;I'm just going to leave it for now.&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;PCA example&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects.packages import importr&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects import globalenv as g&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects import r&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; base     = importr('base')&lt;br /&gt;&gt;&gt;&gt; stats    = importr('stats')&lt;br /&gt;&gt;&gt;&gt; graphics = importr('graphics')&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; # each of these x.y could be replaced by `r`&lt;br /&gt;... m = base.matrix(r.rnorm(100), ncol=5)&lt;br /&gt;&gt;&gt;&gt; pca = stats.princomp(m)&lt;br /&gt;&gt;&gt;&gt; graphics.plot(pca, main="Eigen values")&lt;br /&gt;rpy2.rinterface.NULL&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The graphic is at the top of the post.  I didn't both to print this properly.  See the first post on the docs &lt;a href="http://telliott99.blogspot.com/2011/08/test_18.html"&gt;here&lt;/a&gt;.  But the idea is that although these functions come from the imported modules they are present in the global R namespace (if that's what they call it).  In general, it's better to document your code by using the qualified name.  (I know, I know, I used &lt;code&gt;r&lt;/code&gt; here extensively!  Do as I say, not as I do).&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;kwargs example&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from rpy2.robjects import r&lt;br /&gt;&gt;&gt;&gt; r('''f &lt;- function(x='foo',y='blue') { &lt;br /&gt;...   if (x=='foo')  print(x) &lt;br /&gt;...   else print (y) }''')&lt;br /&gt;&amp;lt;SignatureTranslatedFunction - Python:0x1023d76c8 / R:0x100ef6b58&gt;&lt;br /&gt;&gt;&gt;&gt; f = r['f']&lt;br /&gt;&gt;&gt;&gt; kwargs = {'x':"bar", 'y':"red"}&lt;br /&gt;&gt;&gt;&gt; f(**kwargs)&lt;br /&gt;[1] "red"&lt;br /&gt;&amp;lt;StrVector - Python:0x1023db170 / R:0x102d0fc28&gt;&lt;br /&gt;['red']&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;I guess that's enough for one post.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-767329439316554107?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/767329439316554107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=767329439316554107' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/767329439316554107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/767329439316554107'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/learning-to-use-rpy2-2.html' title='Learning to use RPy2 (2)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-3utQZ8FX1NA/Tk12j-Y7HjI/AAAAAAAABvE/lavoLFlJnr4/s72-c/Screen%2Bshot%2B2011-08-18%2Bat%2B4.26.38%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1665464296153105502</id><published>2011-08-18T13:31:00.003-04:00</published><updated>2011-08-18T16:46:35.339-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='what we&apos;re reading'/><title type='text'>Random Quotes, get your Random Quotes</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;A nice collection of quotes &lt;a href="http://www.superliminal.com/quotes.html"&gt;here&lt;/a&gt;.  Perhaps my favorite:&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;"A month in the laboratory can often save an hour in the library."&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;  -- F. H. Westheimer&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1665464296153105502?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1665464296153105502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1665464296153105502' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1665464296153105502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1665464296153105502'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/random-quotes-get-your-random-quotes.html' title='Random Quotes, get your Random Quotes'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-5676752015907092874</id><published>2011-08-18T13:14:00.002-04:00</published><updated>2011-08-18T13:17:08.530-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='what we&apos;re reading'/><title type='text'>Advice to a neuroscientist.</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Money quote for folks at my place:&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;Third: learn how to do your own data analysis. Know statistics well. Know at least some basic programming/scripting in Python, R, Matlab, etc. This will be of immense value in helping you get your research done efficiently and correctly, without needing to rely on other people's code (and time and commitment). This will become more important as our field becomes more data driven.&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;--Bradley Voytek (&lt;a href="http://blog.ketyov.com/2011/08/career-advice.html"&gt;here&lt;/a&gt;)&lt;br /&gt;h/t &lt;a href="http://blog.ketyov.com/2011/08/career-advice.html"&gt;Tyler Cowen&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My prior on the probability that they'll notice?  0.01    :)  &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-5676752015907092874?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/5676752015907092874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=5676752015907092874' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5676752015907092874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5676752015907092874'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/advice-to-neuroscientist.html' title='Advice to a neuroscientist.'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-6865134259518040125</id><published>2011-08-18T08:00:00.003-04:00</published><updated>2011-08-18T16:45:59.385-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RPy2'/><title type='text'>Learning to use the RPy2 module (1)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Before we tackle turning the Bioconductor example into Python code, I need to review some basic usage of RPy2 as given in the &lt;a href="http://rpy.sourceforge.net/rpy2/doc-dev/html/introduction.html"&gt;docs&lt;/a&gt;.  I posted a bit about this before, but my exploration wasn't systematic, and also the posts contain issues which I solved and described in later posts.&lt;br /&gt;&lt;br /&gt;This exercises the first half of what's on the linked page.  Python code followed output in bold.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import rpy2.robjects as robjects&lt;br /&gt;from rpy2.robjects.packages import importr&lt;br /&gt;&lt;br /&gt;r = robjects.r&lt;br /&gt;g = robjects.globalenv&lt;br /&gt;print type(r)&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&amp;lt;class 'rpy2.robjects.R'&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# from the R base package&lt;br /&gt;# any other name comes from .globalEnv&lt;br /&gt;pi = r['pi']&lt;br /&gt;print pi[0]&lt;br /&gt;print type(pi)&lt;br /&gt;&lt;b&gt;&lt;br /&gt;3.14159265359&lt;br /&gt;&amp;lt;class 'rpy2.robjects.vectors.FloatVector'&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# r is callable with code to be evaluated&lt;br /&gt;piplus = r('piplus = pi + 1')&lt;br /&gt;print type(piplus)&lt;br /&gt;print piplus&lt;br /&gt;print piplus[0]&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&amp;lt;class 'rpy2.robjects.vectors.FloatVector'&gt;&lt;br /&gt;[1] 4.141593&lt;br /&gt;&lt;br /&gt;4.14159265359&lt;br /&gt;[1] 4.141593&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# explicitly get from .globalEnv&lt;br /&gt;piplus_from_g = g['piplus']&lt;br /&gt;print piplus_from_g&lt;br /&gt;print piplus == piplus_from_g&lt;br /&gt;print piplus[0] == piplus_from_g[0]&lt;br /&gt;&lt;b&gt;&lt;br /&gt;False&lt;br /&gt;True&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# define an R function and call it&lt;br /&gt;r('''&lt;br /&gt;    f &lt;- function(start=1,stop = 5) {&lt;br /&gt;    n = 0&lt;br /&gt;    for (j in start:stop) { n = n + j }&lt;br /&gt;    print (n)&lt;br /&gt;    }&lt;br /&gt;''')&lt;br /&gt;&lt;br /&gt;# it's available in .globalEnv&lt;br /&gt;f = g['f']&lt;br /&gt;f()&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;[1] 15&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# but also from the running R process&lt;br /&gt;f = r['f']&lt;br /&gt;f(4)&lt;br /&gt;&lt;b&gt;&lt;br /&gt;[1] 9&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# interpolating an R object into code&lt;br /&gt;letters = robjects.r['letters']&lt;br /&gt;s = letters[1:6].r_repr()&lt;br /&gt;rcode = 'paste(%s, collapse="-")' %(s) &lt;br /&gt;res = robjects.r(rcode)&lt;br /&gt;print(res)&lt;br /&gt;&lt;b&gt;&lt;br /&gt;[1] "b-c-d-e-f"&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# more on calling R functions&lt;br /&gt;rsum = r['sum']&lt;br /&gt;print rsum(robjects.IntVector([1,2,3]))[0]&lt;br /&gt;&lt;b&gt;&lt;br /&gt;6&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# with keyword&lt;br /&gt;rsort = r['sort']&lt;br /&gt;iv = robjects.IntVector([3,1,2])&lt;br /&gt;res = rsort(iv, decreasing=True)&lt;br /&gt;print res.r_repr()&lt;br /&gt;&lt;b&gt;&lt;br /&gt;c(3L, 2L, 1L)&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# plotting&lt;br /&gt;gd = importr('grDevices')&lt;br /&gt;ofn = '/Users/telliott_admin/Desktop/plot.pdf'&lt;br /&gt;gd.pdf(ofn)&lt;br /&gt;&lt;br /&gt;x = robjects.IntVector(range(10)) &lt;br /&gt;y = r.rnorm(10)&lt;br /&gt;r.layout(r.matrix(robjects.IntVector([1,2,3,2]), nrow=2, ncol=2)) &lt;br /&gt;r.plot(r.runif(10), y, xlab="runif", ylab="foo/bar", col="red")&lt;br /&gt;gd.dev_off()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-qh1547ACDUo/Tk0pH2F2f_I/AAAAAAAABu8/2jo7nEBJc1Q/s1600/Screen%2Bshot%2B2011-08-18%2Bat%2B11.00.32%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 263px;" src="http://1.bp.blogspot.com/-qh1547ACDUo/Tk0pH2F2f_I/AAAAAAAABu8/2jo7nEBJc1Q/s320/Screen%2Bshot%2B2011-08-18%2Bat%2B11.00.32%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5642211122920980466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Finally, there are R's special operators like &lt;code&gt;%in%&lt;/code&gt; and &lt;code&gt;%*%&lt;/code&gt;.  I didn't find this yet, so try wrapping it:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;r(''' &lt;br /&gt;is_in &lt;- function(value, container) { &lt;br /&gt;  value %in% container&lt;br /&gt;  }&lt;br /&gt;''')&lt;br /&gt;&lt;br /&gt;is_in = g['is_in']&lt;br /&gt;L = robjects.StrVector(list('abcde'))&lt;br /&gt;print is_in('a',L)&lt;br /&gt;print is_in('f',L)&lt;br /&gt;&lt;b&gt;&lt;br /&gt;[1] TRUE&lt;br /&gt;&lt;br /&gt;[1] FALSE&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;r('''m_mult &lt;- function(m1,m0) { m1 %*% m0 }''')&lt;br /&gt;m_mult = g['m_mult']&lt;br /&gt;r('''mtoi &lt;- function(m) { as.integer(m) }''')&lt;br /&gt;mtoi = g['mtoi']&lt;br /&gt;&lt;br /&gt;# an old friend&lt;br /&gt;m0 = r.matrix(robjects.IntVector([0,1,1,1]), nrow=2)&lt;br /&gt;m = m0&lt;br /&gt;for i in range(10):&lt;br /&gt;    print i + 3, &lt;br /&gt;    m = m_mult(m,m0)&lt;br /&gt;    print mtoi(m)&lt;br /&gt;&lt;b&gt;&lt;br /&gt;3 [1] 1 1 1 2&lt;br /&gt;&lt;br /&gt;4 [1] 1 2 2 3&lt;br /&gt;&lt;br /&gt;5 [1] 2 3 3 5&lt;br /&gt;&lt;br /&gt;6 [1] 3 5 5 8&lt;br /&gt;&lt;br /&gt;7 [1]  5  8  8 13&lt;br /&gt;&lt;br /&gt;8 [1]  8 13 13 21&lt;br /&gt;&lt;br /&gt;9 [1] 13 21 21 34&lt;br /&gt;&lt;br /&gt;10 [1] 21 34 34 55&lt;br /&gt;&lt;br /&gt;11 [1] 34 55 55 89&lt;br /&gt;&lt;br /&gt;12 [1]  55  89  89 144&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-6865134259518040125?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/6865134259518040125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=6865134259518040125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6865134259518040125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6865134259518040125'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/test_18.html' title='Learning to use the RPy2 module (1)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-qh1547ACDUo/Tk0pH2F2f_I/AAAAAAAABu8/2jo7nEBJc1Q/s72-c/Screen%2Bshot%2B2011-08-18%2Bat%2B11.00.32%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3518153584035332804</id><published>2011-08-18T05:33:00.005-04:00</published><updated>2011-08-18T05:52:15.708-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bioconductor'/><title type='text'>Explanation of the example code</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-GAiJkjErbXo/Tkw1mprtiQI/AAAAAAAABuk/tNg-M5LT0Zs/s1600/Screen%2Bshot%2B2011-08-17%2Bat%2B4.18.09%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 317px; height: 320px;" src="http://2.bp.blogspot.com/-GAiJkjErbXo/Tkw1mprtiQI/AAAAAAAABuk/tNg-M5LT0Zs/s320/Screen%2Bshot%2B2011-08-17%2Bat%2B4.18.09%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641943371328882946" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;This is a brief post to explain the R (Bioconductor) code that we used to draw a heat map for gene expression data (&lt;a href="http://"&gt;here&lt;/a&gt; and &lt;a href="http://telliott99.blogspot.com/2011/08/dissecting-expressionset-object.html"&gt;here&lt;/a&gt;).  Again, first we load the example data:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;library('ALL') &lt;br /&gt;data('ALL') &lt;br /&gt;library('limma')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The second group of commands is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;eset &lt;- ALL[,ALL$mol.biol %in% c('BCR/ABL','ALL1/AF4')] &lt;br /&gt;f &lt;- factor(as.character(eset$mol.biol)) &lt;br /&gt;design &lt;- model.matrix(~f) &lt;br /&gt;fit &lt;- eBayes(lmFit(eset,design)) &lt;br /&gt;sel &lt;- p.adjust(fit$p.value[,2]) &lt; 0.05 &lt;br /&gt;esetSel &lt;- eset[sel,]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The first of these constructs a "selector."  The values in &lt;code&gt;ALL$mol.biol&lt;/code&gt; are factors;  two of the possibilities are in the vector &lt;code&gt;c('BCR/ABL','ALL1/AF4')&lt;/code&gt;.  The result is a vector of booleans.  To give a simpler example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; vowels = c('a','e','i','o','u')&lt;br /&gt;&gt; letters[1:6]&lt;br /&gt;[1] "a" "b" "c" "d" "e" "f"&lt;br /&gt;&gt; letters %in% vowels&lt;br /&gt; [1]  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE&lt;br /&gt; [8] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE&lt;br /&gt;[15]  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE&lt;br /&gt;[22] FALSE FALSE FALSE FALSE FALSE&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The vector of True/False values from &lt;code&gt;ALL$mol.biol %in% c('BCR/ABL','ALL1/AF4'&lt;/code&gt; is used to select the appropriate columns from the data, but is acting on the complex ExpressionSet object, as explained last time.  The result is reduced in size.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; dim(eset)&lt;br /&gt;Features  Samples &lt;br /&gt;   12625       47 &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The second line is just a bit of coaxing.  Because the mol.biol descriptions for the smaller eset were derived from a "factor" with 6 possibilities, we remove the other 4 before moving on to model construction:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; f = eset$mol.biol&lt;br /&gt;&gt; class(f)&lt;br /&gt;[1] "factor"&lt;br /&gt;&gt; length(f)&lt;br /&gt;[1] 47&lt;br /&gt;&gt; levels(f)&lt;br /&gt;[1] "ALL1/AF4" "BCR/ABL"  "E2A/PBX1" "NEG"     &lt;br /&gt;[5] "NUP-98"   "p15/p16" &lt;br /&gt;&gt; f = factor(as.character(f))&lt;br /&gt;&gt; class(f)&lt;br /&gt;[1] "factor"&lt;br /&gt;&gt; length(f)&lt;br /&gt;[1] 47&lt;br /&gt;&gt; levels(f)&lt;br /&gt;[1] "ALL1/AF4" "BCR/ABL" &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;The middle two lines is where the magic happens.  I'm going to skip that for the moment.  You can read about it in (Gentleman et al, PMID &lt;a href="http://www.ncbi.nlm.nih.gov/pubmed/15461798"&gt;15461798&lt;/a&gt;).  The result is in the variable `fit`.  One of its sub-objects is a list of p-values:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; class(fit$p.value)&lt;br /&gt;[1] "matrix"&lt;br /&gt;&gt; fit$p.value[1:3,]&lt;br /&gt;           (Intercept)   fBCR/ABL&lt;br /&gt;1000_at   2.713661e-58 0.05437095&lt;br /&gt;1001_at   3.001944e-43 0.24423133&lt;br /&gt;1002_f_at 2.273600e-46 0.10091357&lt;br /&gt;&gt; colnames(fit$p.value)&lt;br /&gt;[1] "(Intercept)" "fBCR/ABL"   &lt;br /&gt;&gt; pv = fit$p.value[,2]&lt;br /&gt;&gt; class(pv)&lt;br /&gt;[1] "numeric"&lt;br /&gt;&gt; pv[1:4]&lt;br /&gt;   1000_at    1001_at  1002_f_at  1003_s_at &lt;br /&gt;0.05437095 0.24423133 0.10091357 0.30303775 &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;p.adjust&lt;/code&gt; is a correction for the large number of comparisons.  You can read about it by doing &lt;code&gt;?p.adjust&lt;/code&gt;.  I wasn't clear on which is the default method, but it's not &lt;a href="http://en.wikipedia.org/wiki/Bonferroni_correction"&gt;Bonferroni&lt;/a&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; r1 = p.adjust(pv)&lt;br /&gt;&gt; r2 = p.adjust(pv,method='bonferroni')&lt;br /&gt;&gt; all(r1 == r2)&lt;br /&gt;[1] FALSE&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;So we just construct a selector for those rows with p &lt; 0.05, and again, whittle down the ExpressionSet to something manageable:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; sel &lt;- p.adjust(pv) &lt; 0.05 &lt;br /&gt;&gt; esetSel &lt;- eset[sel,]&lt;br /&gt;&gt; dim(esetSel)&lt;br /&gt;Features  Samples &lt;br /&gt;     165       47 &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;In the third part, we draw the heatmap.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;color.map &lt;- function(s) { &lt;br /&gt;if (s=='ALL1/AF4') 'red' else 'blue'} &lt;br /&gt;patient.colors &lt;- unlist(lapply(esetSel$mol.biol,color.map)) &lt;br /&gt;heatmap(exprs(esetSel), &lt;br /&gt;col=topo.colors(100), &lt;br /&gt;ColSideColors=patient.colors)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;In the first two lines we construct a function called &lt;code&gt;color.map&lt;/code&gt;, and then use it to construct a vector of &lt;code&gt;patient.colors&lt;/code&gt;.  This is for the colored bars at the top of the plot.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; color.map &lt;- function(s) { &lt;br /&gt;+ if (s=='ALL1/AF4') 'red' else 'blue'} &lt;br /&gt;&gt; &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We use &lt;code&gt;lapply&lt;/code&gt; to feed &lt;code&gt;values&lt;/code&gt; to our function, but the result is a list.  So we use &lt;code&gt;unlist&lt;/code&gt; to extract what we want.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; values = esetSel$mol.biol&lt;br /&gt;&gt; values[1:4]&lt;br /&gt;[1] BCR/ABL  BCR/ABL  ALL1/AF4 BCR/ABL &lt;br /&gt;6 Levels: ALL1/AF4 BCR/ABL E2A/PBX1 ... p15/p16&lt;br /&gt;&gt; colors = lapply(values,color.map)&lt;br /&gt;&gt; class(colors)&lt;br /&gt;[1] "list"&lt;br /&gt;&gt; colors[1:2]&lt;br /&gt;[[1]]&lt;br /&gt;[1] "blue"&lt;br /&gt;&lt;br /&gt;[[2]]&lt;br /&gt;[1] "blue"&lt;br /&gt;&lt;br /&gt;&gt; patient.colors = unlist(colors)&lt;br /&gt;&gt; patient.colors[1:4]&lt;br /&gt;[1] "blue" "blue" "red"  "blue"&lt;br /&gt;&gt; class(patient.colors)&lt;br /&gt;[1] "character"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We draw the heatmap with the command:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;heatmap(exprs(esetSel)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;All the rest is eye candy.  In particular, we use the &lt;code&gt;topo.colors&lt;/code&gt;.  Without that, we get the default.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-qbGvdSri-N8/TkzdRy__rVI/AAAAAAAABu0/pm3Q5BgwWps/s1600/Screen%2Bshot%2B2011-08-18%2Bat%2B5.29.52%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 317px; height: 320px;" src="http://1.bp.blogspot.com/-qbGvdSri-N8/TkzdRy__rVI/AAAAAAAABu0/pm3Q5BgwWps/s320/Screen%2Bshot%2B2011-08-18%2Bat%2B5.29.52%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5642127731006090578" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;With the topo.colors, we would get colors as in the graphic at the top of the post.  &lt;br /&gt;&lt;code&gt;&lt;br /&gt;heatmap(exprs(esetSel),col=topo.colors(100))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The last argument to heatmap gives us the bars on the columns to identify the sample by translocation.&lt;br /&gt;&lt;br /&gt;We've explained everything but the actual statistical model fitting.  That's for another time.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3518153584035332804?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3518153584035332804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3518153584035332804' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3518153584035332804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3518153584035332804'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/explanation-of-example-code.html' title='Explanation of the example code'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-GAiJkjErbXo/Tkw1mprtiQI/AAAAAAAABuk/tNg-M5LT0Zs/s72-c/Screen%2Bshot%2B2011-08-17%2Bat%2B4.18.09%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-9012497495010504284</id><published>2011-08-17T20:36:00.003-04:00</published><updated>2011-08-17T20:51:56.080-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bioconductor'/><title type='text'>Dissecting an ExpressionSet object</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Last time, we were in R using some Bioconductor code.  If we do this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;library('ALL')&lt;br /&gt;data('ALL')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;then the variable &lt;code&gt;ALL&lt;/code&gt; is available&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; ALL&lt;br /&gt;ExpressionSet (storageMode: lockedEnvironment)&lt;br /&gt;assayData: 12625 features, 128 samples &lt;br /&gt;  element names: exprs &lt;br /&gt;protocolData: none&lt;br /&gt;phenoData&lt;br /&gt;  sampleNames: 01005 01010 ... LAL4 (128 total)&lt;br /&gt;  varLabels: cod diagnosis ... date last seen (21 total)&lt;br /&gt;  varMetadata: labelDescription&lt;br /&gt;featureData: none&lt;br /&gt;experimentData: use 'experimentData(object)'&lt;br /&gt;  pubMedIds: 14684422 16243790 &lt;br /&gt;Annotation: hgu95av2 &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;(note: your output may vary slightly depending on the R and Bioconductor version.)&lt;br /&gt;&lt;br /&gt;Obviously the object that &lt;code&gt;ALL&lt;/code&gt; refers to is complicated.  Its components are called "slots" and they are accessible with the syntax:  &lt;code&gt;object_name@slot_name&lt;/code&gt;.  For example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;pData = ALL@phenoData&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;You can find out which slots are available by parsing the above output or just doing:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; slotNames(ALL)&lt;br /&gt;[1] "assayData"         "phenoData"        &lt;br /&gt;[3] "featureData"       "experimentData"   &lt;br /&gt;[5] "annotation"        "protocolData"     &lt;br /&gt;[7] ".__classVersion__"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;In turn the slots are also complex objects.  Technically, a phenoData object is:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; class(ALL@phenoData)&lt;br /&gt;[1] "AnnotatedDataFrame"&lt;br /&gt;attr(,"package")&lt;br /&gt;[1] "Biobase"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;More important, its sub-objects are available with the syntax &lt;code&gt;slot_name$sub-object_name&lt;/code&gt;.  But first we must discover which names are available:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; pData = ALL@phenoData&lt;br /&gt;&gt; varLabels(pData)&lt;br /&gt; [1] "cod"            "diagnosis"      "sex"           &lt;br /&gt; [4] "age"            "BT"             "remission"     &lt;br /&gt; [7] "CR"             "date.cr"        "t(4;11)"       &lt;br /&gt;[10] "t(9;22)"        "cyto.normal"    "citog"         &lt;br /&gt;[13] "mol.biol"       "fusion protein" "mdr"           &lt;br /&gt;[16] "kinet"          "ccr"            "relapse"       &lt;br /&gt;[19] "transplant"     "f.u"            "date last seen"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;So, for example:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; pData$sex[1:5]&lt;br /&gt;[1] M M F M M&lt;br /&gt;Levels: F M&lt;br /&gt;&lt;br /&gt;&gt; pData$mol.biol[1:5]&lt;br /&gt;[1] BCR/ABL  NEG      BCR/ABL  ALL1/AF4 NEG     &lt;br /&gt;Levels: ALL1/AF4 BCR/ABL E2A/PBX1 NEG NUP-98 p15/p16&lt;br /&gt;&lt;br /&gt;&gt; levels(pData$mol.biol)&lt;br /&gt;[1] "ALL1/AF4" "BCR/ABL"  "E2A/PBX1" "NEG"     &lt;br /&gt;[5] "NUP-98"   "p15/p16" &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;At this level, the objects are reasonably simple.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; class(pData$mol.biol)&lt;br /&gt;[1] "factor"&lt;br /&gt;&gt; class(pData$sex)&lt;br /&gt;[1] "factor"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;Don't forget the other method names:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; sampleNames(pData)[1:5]&lt;br /&gt;[1] "01005" "01010" "03002" "04006" "04007"&lt;br /&gt;&lt;br /&gt;&gt; featureNames(ALL)[1:8]&lt;br /&gt;[1] "1000_at"   "1001_at"   "1002_f_at" "1003_s_at"&lt;br /&gt;[5] "1004_at"   "1005_at"   "1006_at"   "1007_s_at"&lt;br /&gt;&lt;br /&gt;&gt; head(varMetadata(pData))&lt;br /&gt;                                                         labelDescription&lt;br /&gt;cod                                                            Patient ID&lt;br /&gt;diagnosis                                               Date of diagnosis&lt;br /&gt;sex                                                 Gender of the patient&lt;br /&gt;age                                           Age of the patient at entry&lt;br /&gt;BT                             does the patient have B-cell or T-cell ALL&lt;br /&gt;remission  Complete remission(CR), refractory(REF) or NA. Derived from CR&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And, I should point out that (without actually knowing it at the time) I shadowed a real function in the namespace by assigning to &lt;code&gt;pData&lt;/code&gt; above.&lt;br /&gt;&lt;br /&gt;If we reboot R and do:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;library('ALL')&lt;br /&gt;data('ALL')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;we can use a different method for access:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; p = pData(ALL)&lt;br /&gt;&gt; class(p)&lt;br /&gt;[1] "data.frame"&lt;br /&gt;&gt; names(p)&lt;br /&gt; [1] "cod"            "diagnosis"      "sex"           &lt;br /&gt; [4] "age"            "BT"             "remission"     &lt;br /&gt; [7] "CR"             "date.cr"        "t(4;11)"       &lt;br /&gt;[10] "t(9;22)"        "cyto.normal"    "citog"         &lt;br /&gt;[13] "mol.biol"       "fusion protein" "mdr"           &lt;br /&gt;[16] "kinet"          "ccr"            "relapse"       &lt;br /&gt;[19] "transplant"     "f.u"            "date last seen"&lt;br /&gt;&gt; p$sex[1:5]&lt;br /&gt;[1] M M F M M&lt;br /&gt;Levels: F M&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;The very first slot holds the gene expression data.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; aData = ALL@assayData&lt;br /&gt;&gt; class(aData)&lt;br /&gt;[1] "environment"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;I'm not really sure what that class is.  And, unfortunately, it is not easy to find which sub-object names are available for this slot:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; names(aData)&lt;br /&gt;NULL&lt;br /&gt;&gt; elements(aData)&lt;br /&gt;Error: could not find function "elements"&lt;br /&gt;&gt; elementNames(aData)&lt;br /&gt;Error: could not find function "elementNames"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;except we can probably guess that &lt;code&gt;exprs&lt;/code&gt; is one (based on the output of the call `ALL` above:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; e = aData$exprs&lt;br /&gt;&gt; class(e)&lt;br /&gt;[1] "matrix"&lt;br /&gt;&gt; e[1:3,1:3]&lt;br /&gt;             01005    01010    03002&lt;br /&gt;1000_at   7.597323 7.479445 7.567593&lt;br /&gt;1001_at   5.046194 4.932537 4.799294&lt;br /&gt;1002_f_at 3.900466 4.208155 3.886169&lt;br /&gt;&gt; dim(e)&lt;br /&gt;[1] 12625   128&lt;br /&gt;&gt; rownames(e)[1:8]&lt;br /&gt;[1] "1000_at"   "1001_at"   "1002_f_at" "1003_s_at"&lt;br /&gt;[5] "1004_at"   "1005_at"   "1006_at"   "1007_s_at"&lt;br /&gt;&gt; colnames(e)[1:3]&lt;br /&gt;[1] "01005" "01010" "03002"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;-------------------------------------------------------&lt;br /&gt;So far, so good.&lt;br /&gt;&lt;br /&gt;Now, obviously we can &lt;i&gt;select&lt;/i&gt; rows and columns of a matrix like &lt;code&gt;ALL@assayData$exprs&lt;/code&gt;, which we've assigned to the variable &lt;code&gt;e&lt;/code&gt;:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; e[1:2,1:3]&lt;br /&gt;           01005    01010    03002&lt;br /&gt;1000_at 7.597323 7.479445 7.567593&lt;br /&gt;1001_at 5.046194 4.932537 4.799294&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;What the Bioconductor guys have done is make this assignment valid for the ExpressionSet object itself:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; ALL[1:2,1:3]&lt;br /&gt;ExpressionSet (storageMode: lockedEnvironment)&lt;br /&gt;assayData: 2 features, 3 samples &lt;br /&gt;  element names: exprs &lt;br /&gt;protocolData: none&lt;br /&gt;phenoData&lt;br /&gt;  sampleNames: 01005 01010 03002&lt;br /&gt;  varLabels: cod diagnosis ... date last seen (21 total)&lt;br /&gt;  varMetadata: labelDescription&lt;br /&gt;featureData: none&lt;br /&gt;experimentData: use 'experimentData(object)'&lt;br /&gt;  pubMedIds: 14684422 16243790 &lt;br /&gt;Annotation: hgu95av2&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That's either very cool or very confusing depending on where you sit.&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;Finally, the annotation.  This requires another package:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ann = ALL@annotation&lt;br /&gt;&gt; ann&lt;br /&gt;[1] "hgu95av2"&lt;br /&gt;&lt;br /&gt;library('annaffy')&lt;br /&gt;probeids &lt;- featureNames(ALL)&lt;br /&gt;symbols &lt;- aafSymbol(probeids, 'hgu95av2')&lt;br /&gt;&lt;br /&gt;&gt; symbols &lt;- aafSymbol(probeids, 'hgu95av2')&lt;br /&gt;[1] "You are missing hgu95av2 looking to see if it is available."&lt;br /&gt;Warning: unable to access index for repository http://brainarray.mbni.med.umich.edu/bioc/bin/macosx/leopard/contrib/2.11&lt;br /&gt;Package hgu95av2 is available for download, would you like to install? [y/n] &lt;br /&gt;y&lt;br /&gt;Warning: unable to access index for repository http://brainarray.mbni.med.umich.edu/bioc/bin/macosx/leopard/contrib/2.11&lt;br /&gt;trying URL 'http://bioconductor.org/packages/2.6/data/annotation/bin/macosx/leopard/contrib/2.11/hgu95av2_2.2.0.tgz'&lt;br /&gt;Content type 'application/x-gzip' length 9340297 bytes (8.9 Mb)&lt;br /&gt;opened URL&lt;br /&gt;==================================================&lt;br /&gt;downloaded 8.9 Mb&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The downloaded packages are in&lt;br /&gt;	/var/folders/3g/3gHxNStTGZaWkGngOL39-++++TI/-Tmp-//RtmptUUJr1/downloaded_packages&lt;br /&gt;Loading required package: hgu95av2&lt;br /&gt;&lt;br /&gt;******* Deprecation warning *******:&lt;br /&gt;&lt;br /&gt;The package 'hgu95av2' is deprecated and will not be supported in the future. &lt;br /&gt;&lt;br /&gt;Instead we strongly reccomend that you should start using the 'hgu95av2.db' package. &lt;br /&gt;&lt;br /&gt;We hope you will enjoy these new packages.  If you still have questions, you can search &lt;br /&gt;(http://dir.gmane.org/gmane.science.biology.informatics.conductor) or ask the mailing list &lt;br /&gt;(http://bioconductor.org/docs/mailList.html).&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;To repeat:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;library('annaffy')&lt;br /&gt;probeids &lt;- featureNames(ALL)&lt;br /&gt;symbols &lt;- aafSymbol(probeids, 'hgu95av2')&lt;br /&gt;&gt; class(symbols)&lt;br /&gt;[1] "aafList"&lt;br /&gt;&gt; genenames = getText(symbols)&lt;br /&gt;&gt; genenames[1:3]&lt;br /&gt;[1] "MAPK3"   "TIE1"    "CYP2C19"&lt;br /&gt;&gt; probeids[1:3]&lt;br /&gt;[1] "1000_at"   "1001_at"   "1002_f_at"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We'll write this all down on a couple post-it notes and put it on the monitor for reference.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-9012497495010504284?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/9012497495010504284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=9012497495010504284' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/9012497495010504284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/9012497495010504284'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/dissecting-expressionset-object.html' title='Dissecting an ExpressionSet object'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7858916209305209214</id><published>2011-08-17T17:15:00.005-04:00</published><updated>2011-08-18T05:12:20.700-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bioconductor'/><title type='text'>A first heat map using Bioconductor</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-GAiJkjErbXo/Tkw1mprtiQI/AAAAAAAABuk/tNg-M5LT0Zs/s1600/Screen%2Bshot%2B2011-08-17%2Bat%2B4.18.09%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 317px; height: 320px;" src="http://2.bp.blogspot.com/-GAiJkjErbXo/Tkw1mprtiQI/AAAAAAAABuk/tNg-M5LT0Zs/s320/Screen%2Bshot%2B2011-08-17%2Bat%2B4.18.09%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641943371328882946" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I don't recall what the exact Google search target was that turned up a post about making a heatmap of gene expression data,  but it really changed my life.  It lead me to these two pages describing how to do it in R (&lt;a href="http://www2.warwick.ac.uk/fac/sci/moac/students/peter_cock/r/heatmap/"&gt;here&lt;/a&gt;) and Python (&lt;a href="http://www2.warwick.ac.uk/fac/sci/moac/students/peter_cock/python/heatmap/#Python"&gt;here&lt;/a&gt;), and that motivated me to get into R, as much as I've been able to in spite of all I don't like about it. &lt;br /&gt;&lt;br /&gt;I thought I'd work on this a little bit again;  it's been 3 years or so since I gave a couple of talks about this, so I'm rusty, but it'll be fun.  I would recommend that you go through the original posts by Peter Cock first.  I'll try to add something of my own.&lt;br /&gt;&lt;br /&gt;Of course, it's all based on the &lt;a href="http://www.bioconductor.org/"&gt;Bioconductor&lt;/a&gt; project in R, and there is a very nice write-up in the original paper (Gentleman et al, PMID &lt;a href="http://www.ncbi.nlm.nih.gov/pubmed/15461798"&gt;15461798&lt;/a&gt;).  I even bought the book (our library sucks), and it's pretty good too, especially if you are serious about the field.&lt;br /&gt;&lt;br /&gt;To begin with, to motivate things, we will recreate the graphic.  We need a couple of R packages from Bioconductor to do this.  You could get them from the Package Installer, but I was having trouble and so I tried this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;source("http://bioconductor.org/biocLite.R")&lt;br /&gt;biocLite('Biobase')&lt;br /&gt;biocLite('ALL')&lt;br /&gt;biocLite('limma')&lt;br /&gt;biocLite('annaffy')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Note:  all these lines would actually look like this in R:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; source("http://bioconductor.org/biocLite.R")&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;For most of the commands here, I've left out the prompt so you can more easily copy and paste them.  And I'm not showing the info that's printed as the packages are downloaded and installed.  &lt;br /&gt;&lt;br /&gt;We're going to just quickly do the plots, then later I'll explain more about it.  First we need to load two modules and some data:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;library('ALL')&lt;br /&gt;data('ALL')&lt;br /&gt;library('limma')&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The first command will output:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Loading required package: Biobase&lt;br /&gt;&lt;br /&gt;Welcome to Bioconductor&lt;br /&gt;&lt;br /&gt;  Vignettes contain introductory material. To view, type&lt;br /&gt;  'openVignette()'. To cite Bioconductor, see&lt;br /&gt;  'citation("Biobase")' and for packages 'citation(pkgname)'.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next we do the analysis (I know this won't make much sense yet, but we're just making sure we get the graphic without an error):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;eset &lt;- ALL[,ALL$mol.biol %in% c('BCR/ABL','ALL1/AF4')]&lt;br /&gt;f &lt;- factor(as.character(eset$mol.biol))&lt;br /&gt;design &lt;- model.matrix(~f)&lt;br /&gt;fit &lt;- eBayes(lmFit(eset,design))&lt;br /&gt;sel &lt;- p.adjust(fit$p.value[,2]) &lt; 0.05&lt;br /&gt;esetSel &lt;- eset[sel,]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And in the third part we plot the data:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;color.map &lt;- function(s) {&lt;br /&gt;  if (s=='ALL1/AF4') 'red' else 'blue'}&lt;br /&gt;patient.colors &lt;- unlist(lapply(esetSel$mol.biol,color.map))&lt;br /&gt;heatmap(exprs(esetSel),&lt;br /&gt;  col=topo.colors(100),&lt;br /&gt;  ColSideColors=patient.colors)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The graphic is at the top of the post.&lt;br /&gt;&lt;br /&gt;An overview of what we've done.  We filtered for all samples with one of two chromosomal translocations.  In the plots, the columns from the 'ALL1/AF4' samples are red, those with 'BCR/ABL' are blue.  We now have 47 samples. &lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; dim(eset)&lt;br /&gt;Features  Samples &lt;br /&gt;   12625       47 &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Each sample has 12625 "features"---gene expression measurements.  We've done some fancy statistics and then filtered for those with p &lt; 0.05 (correcting for the large number of measurements).  In the end, we have 165 genes of interest to plot.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt; dim(esetSel)&lt;br /&gt;Features  Samples &lt;br /&gt;     165       47&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;By default, heatmap does clustering and draws dendrograms, but you can turn this off.  Let's turn off the column clustering only, and since we haven't substituted the real gene names, let's turn that off too:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;heatmap(exprs(esetSel),&lt;br /&gt;  col=topo.colors(100),&lt;br /&gt;  Colv=NA,&lt;br /&gt;  ColSideColors=patient.colors,&lt;br /&gt;  labRow=NA)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-k68ojFMWAhQ/Tkw1m5WAPnI/AAAAAAAABus/vs2bdFemFD8/s1600/Screen%2Bshot%2B2011-08-17%2Bat%2B5.41.04%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 285px;" src="http://2.bp.blogspot.com/-k68ojFMWAhQ/Tkw1m5WAPnI/AAAAAAAABus/vs2bdFemFD8/s320/Screen%2Bshot%2B2011-08-17%2Bat%2B5.41.04%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641943375532801650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;More later on this.  Our goal is to understand more about "ExpressionSet" objects and the kinds of manipulation that are possible, the second is to see how much of this we can do from Python (using &lt;a href="http://rpy.sourceforge.net/rpy2.html"&gt;rpy2&lt;/a&gt;), so that the code is transparent and makes intuitive sense.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7858916209305209214?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7858916209305209214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7858916209305209214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7858916209305209214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7858916209305209214'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/first-heat-map-using-bioconductor.html' title='A first heat map using Bioconductor'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-GAiJkjErbXo/Tkw1mprtiQI/AAAAAAAABuk/tNg-M5LT0Zs/s72-c/Screen%2Bshot%2B2011-08-17%2Bat%2B4.18.09%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3266603236020353428</id><published>2011-08-17T04:25:00.004-04:00</published><updated>2011-08-17T04:32:57.496-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>Zenoss</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;I found this &lt;a href="http://serverfault.com/questions/148658/know-any-good-network-monitoring-tool-for-osx"&gt;question&lt;/a&gt; on SF about network monitoring for OS X.  One of answers described an open source solution called &lt;a href="http://community.zenoss.org/index.jspa"&gt;Zenoss&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;From the looks of things it's very powerful.  Here is a slightly old &lt;a href="http://blog.nuclearbunny.org/tag/zenoss/"&gt;post&lt;/a&gt; about using it on OS X.  &lt;br /&gt;&lt;br /&gt;I downloaded and installed Zenoss.  Unfortunately, it made my system feel unresponsive, even when the App was not running.  (There are a bunch of process that run at startup, and eat up CPU).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/--6Kq9wbDnbk/Tkt7e7R8-SI/AAAAAAAABuc/_kFlWZWWIEA/s1600/Screen%2BShot%2B2011-08-17%2Bat%2B3.37.36%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 89px;" src="http://1.bp.blogspot.com/--6Kq9wbDnbk/Tkt7e7R8-SI/AAAAAAAABuc/_kFlWZWWIEA/s320/Screen%2BShot%2B2011-08-17%2Bat%2B3.37.36%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641738729450961186" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Luckily, there is an uninstaller.  I couldn't figure out how to get there in the Finder, but I just did:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;open -a /usr/local/zenoss/uninstall.app/&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It's probably no surprise that the uninstaller took more than 5 min to run, but it seems at least to have done its job and now everything is nice and snappy again.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3266603236020353428?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3266603236020353428/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3266603236020353428' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3266603236020353428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3266603236020353428'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/zenoss.html' title='Zenoss'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/--6Kq9wbDnbk/Tkt7e7R8-SI/AAAAAAAABuc/_kFlWZWWIEA/s72-c/Screen%2BShot%2B2011-08-17%2Bat%2B3.37.36%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-4979701459148852859</id><published>2011-08-16T08:00:00.000-04:00</published><updated>2011-08-16T13:01:25.089-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='duly quoted'/><title type='text'>High standards</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;The nice thing about standards is that there are so many to choose from. And if you really don't like all the standards you just have to wait another year until the one arises you are looking for.&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;-- A. Tanenbaum, "Introduction to Computer Networks", quoted &lt;a href="http://httpd.apache.org/docs/2.2/ssl/ssl_intro.html"&gt;here&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-4979701459148852859?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/4979701459148852859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=4979701459148852859' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4979701459148852859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4979701459148852859'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/high-standards.html' title='High standards'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7290086183203548532</id><published>2011-08-15T08:30:00.003-04:00</published><updated>2011-08-17T04:35:47.523-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Trying Ubuntu Linux (6)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Continuing with my Ubuntu Linux (11.0.4) server running in a VirtualBox VM under Mac OS X Lion, and making its capabilities available to other machines on my LAN.  In two previous posts I described my search for a solution (&lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-4.html"&gt;here&lt;/a&gt;), and the actual solution (&lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-5.html"&gt;here&lt;/a&gt;), which used port forwarding with VirtualBox networking in NAT mode.&lt;br /&gt;&lt;br /&gt;There is at least one other possible solution, which is to do the networking in bridged mode.  To quote the &lt;a href="http://www.virtualbox.org/manual/ch06.html"&gt;docs&lt;/a&gt;:&lt;br /&gt;&lt;font color='blue'&gt;&lt;br /&gt;&lt;blockquote&gt;With bridged networking, VirtualBox uses a device driver on your host system that filters data from your physical network adapter. This driver is therefore called a "net filter" driver. This allows VirtualBox to intercept data from the physical network and inject data into it, effectively creating a new network interface in software. When a guest is using such a new software interface, it looks to the host system as though the guest were physically connected to the interface using a network cable: the host can send data to the guest through that interface and receive data from it. This means that you can set up routing or bridging between the guest and the rest of your network.&lt;br /&gt;&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;To begin with I did something (that may not be necessary), I turned off the NAT rule from before (in OS X):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;VBoxManage modifyvm Ubuntu --natpf1 delete "server"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then I set networking to bridged in the VirtualBox Settings:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-lJZ7C53d120/TkmBMCQ72JI/AAAAAAAABuI/IE1Kwgn3dV0/s1600/Screen%2BShot%2B2011-08-15%2Bat%2B4.20.26%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 267px;" src="http://3.bp.blogspot.com/-lJZ7C53d120/TkmBMCQ72JI/AAAAAAAABuI/IE1Kwgn3dV0/s320/Screen%2BShot%2B2011-08-15%2Bat%2B4.20.26%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641182052024572050" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And restarted Apache (in Ubuntu):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo /etc/init.d/apache2 restart &lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ifconfig&lt;/code&gt; gives me the IP address that we have obtained from the DHCP server in &lt;a href="http://www.apple.com/airportextreme/"&gt;Airport Extreme&lt;/a&gt;: &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-W1HUR7JERdg/TkmBL7qL7NI/AAAAAAAABuA/Qp9e14zm9PY/s1600/Screen%2BShot%2B2011-08-15%2Bat%2B4.19.55%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 206px;" src="http://2.bp.blogspot.com/-W1HUR7JERdg/TkmBL7qL7NI/AAAAAAAABuA/Qp9e14zm9PY/s320/Screen%2BShot%2B2011-08-15%2Bat%2B4.19.55%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641182050251435218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If I use the AirPort Utility I can see the corresponding MAC and IP addresses. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-DTa71zqXVtA/Tkq2dPx7ryI/AAAAAAAABuQ/h6hJYcs5OyY/s1600/Screen%2BShot%2B2011-08-16%2Bat%2B2.26.27%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 65px;" src="http://4.bp.blogspot.com/-DTa71zqXVtA/Tkq2dPx7ryI/AAAAAAAABuQ/h6hJYcs5OyY/s320/Screen%2BShot%2B2011-08-16%2Bat%2B2.26.27%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641522096803393314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now if I go to another machine on the network and point Safari at that IP, it works:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-2anGPGdBsoA/TkmBL-0FdaI/AAAAAAAABt4/X6JjZUC8mFA/s1600/Screen%2BShot%2B2011-08-15%2Bat%2B4.19.30%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 139px;" src="http://4.bp.blogspot.com/-2anGPGdBsoA/TkmBL-0FdaI/AAAAAAAABt4/X6JjZUC8mFA/s320/Screen%2BShot%2B2011-08-15%2Bat%2B4.19.30%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5641182051098260898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[ UPDATE:  In the screenshot we specified port 8080, and that works because of what we did last time.  But you can also do the ipadress only and it works too.  ]&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7290086183203548532?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7290086183203548532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7290086183203548532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7290086183203548532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7290086183203548532'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-6.html' title='Trying Ubuntu Linux (6)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-lJZ7C53d120/TkmBMCQ72JI/AAAAAAAABuI/IE1Kwgn3dV0/s72-c/Screen%2BShot%2B2011-08-15%2Bat%2B4.20.26%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3080304736738283331</id><published>2011-08-14T15:07:00.013-04:00</published><updated>2011-08-24T07:42:11.922-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pretty code'/><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Pretty code</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;[ UPDATE2:  In an earlier version of this post, I missed one HTML tag in the code below, as a result the example wouldn't run as described when copy/pasted.  Sorry. ]&lt;br /&gt;I've been looking into solutions for posting code on the blog.  Since the beginning, I've used &lt;code&gt;&amp;lt;table&gt;&lt;/code&gt; tags like this:&lt;br /&gt;&lt;code&gt; &amp;lt;div style="overflow-x: scroll "&gt; &lt;br /&gt;&amp;lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt; &lt;br /&gt;&amp;lt;tbody&gt;&amp;lt;tr&gt;&amp;lt;td&gt;&amp;lt;pre style=" hidden;font-family:monaco;"&gt; &lt;br /&gt;my code here &lt;br /&gt;&amp;lt;/pre&gt;&amp;lt;/table&gt;&amp;lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;With results looking like a bit like this, but larger  :) &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-8pGAsqMs4wo/TkhNH2fkVtI/AAAAAAAABtY/5stNs_wF828/s1600/Screen%2BShot%2B2011-08-14%2Bat%2B6.32.32%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 86px;" src="http://2.bp.blogspot.com/-8pGAsqMs4wo/TkhNH2fkVtI/AAAAAAAABtY/5stNs_wF828/s320/Screen%2BShot%2B2011-08-14%2Bat%2B6.32.32%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5640843330563888850" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;I borrowed the technique from Peter Norvig.  He's moved on, but I hadn't. &lt;br /&gt;&lt;br /&gt;In the last few days Blogger changed something that inserts newlines into such tables.  I found another guy who &lt;a href="http://www.google.com/support/forum/p/blogger/thread?tid=127e0c941a8cbe20&amp;hl=en"&gt;noticed&lt;/a&gt;, but no solution.  (Perhaps if I used the "new" editor?). &lt;br /&gt;&lt;br /&gt;So, I googled around for &lt;a href="http://en.wikipedia.org/wiki/Syntax_highlighting"&gt;syntax highlighting&lt;/a&gt;.  &lt;a href="http://www.webdesignbooth.com/9-useful-javascript-syntax-highlighting-scripts/"&gt;Here&lt;/a&gt; is a listing of a bunch of methods.  The one I decided to try is &lt;a href="http://code.google.com/p/google-code-prettify/downloads/detail?name=prettify-small-1-Jun-2011.tar.bz2&amp;can=2&amp;q="&gt;google-code-prettify&lt;/a&gt;.  Like all the methods, it uses javascript and some css to do its work.  Instructions are in the &lt;a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html"&gt;readme&lt;/a&gt;.  The footprint in the html is pretty small, and I like the minimalist style. &lt;br /&gt;&lt;br /&gt;To test it, I downloaded the distribution (see the link), and then put a file with the following html in the same directory as the source: &lt;br /&gt;&lt;br /&gt;&lt;code&gt; &lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&gt; &lt;br /&gt;&amp;lt;!DOCTYPE html&gt; &lt;br /&gt;&amp;lt;html ... &gt; &lt;br /&gt;. &lt;br /&gt;&amp;lt;head ... &gt; &lt;br /&gt;. &lt;br /&gt;&amp;lt;link href="prettify.css" type="text/css" rel="stylesheet" /&gt; &lt;br /&gt;&amp;lt;script type="text/javascript" src="prettify.js"&gt;&amp;lt;/script&gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;/head&gt; &lt;br /&gt;&amp;lt;body onload="prettyPrint()"&gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;pre class="prettyprint" lang-python&gt; &lt;br /&gt;def f(n, s='abc'): &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspprint 'Hello world!' &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspfor i in range(n): &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp# this is a loop &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspprint s &lt;br /&gt;&amp;lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;pre class="prettyprint"&gt; &lt;br /&gt;#include &amp;lt;math.h&gt; &lt;br /&gt;#include "Python.h" &lt;br /&gt;&lt;br /&gt;int process (const char *c, double f) { &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspint i = 0; &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspif (c[0] == 'c') { &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspi = floor(f); &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp} &lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspreturn i; &lt;br /&gt;} &lt;br /&gt;&amp;lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&gt; &lt;br /&gt;&amp;lt;/html&gt; &lt;br /&gt;&lt;/code&gt; &lt;br /&gt;&lt;br /&gt;and then drag-n-dropped it on Safari: &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-BaBsUwj2yfQ/TkhPobw0hiI/AAAAAAAABtg/8rGSV9DuEbY/s1600/Screen%2BShot%2B2011-08-14%2Bat%2B6.42.44%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 283px;" src="http://4.bp.blogspot.com/-BaBsUwj2yfQ/TkhPobw0hiI/AAAAAAAABtg/8rGSV9DuEbY/s320/Screen%2BShot%2B2011-08-14%2Bat%2B6.42.44%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5640846089347434018" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;One small problem is this note: &lt;br /&gt;&lt;br /&gt;&lt;font color="blue"&gt; &lt;br /&gt;&lt;blockquote&gt;Include the script and stylesheets in your document (you will need to make sure the css and js file are on your server, and adjust the paths in the script and link tag)&lt;/blockquote&gt;&lt;/font&gt; &lt;br /&gt;&lt;br /&gt;Server, what server? &lt;br /&gt;&lt;br /&gt;Seriously, I'd be happy to do it, but I don't want to pay Comcast $$ for the privilege. &lt;br /&gt;&lt;br /&gt;However, there is a very nice answer on Stack Overflow (&lt;a href="http://stackoverflow.com/questions/1852537/how-to-use-prettify-with-blogger-blogspot"&gt;here&lt;/a&gt;) that shows how to embed the relatively simple css instructions into the html document.  Then you just load the code from  &lt;br /&gt;&lt;br /&gt;&lt;code&gt; &lt;br /&gt;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js &lt;br /&gt;http://google-code-prettify.googlecode.com/svn/trunk/src/lang-css.js &lt;br /&gt;&lt;/code&gt; &lt;br /&gt;&lt;br /&gt;I tested it in a simple html document and it worked.  Now I'll have to try to incorporate all this into a Blogger template. &lt;br /&gt;&lt;br /&gt;[ UPDATE:  I see it choked on the &lt;code&gt;&amp;lt;math.h&gt;&lt;/code&gt;.  I'll have to remember that. ] &lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3080304736738283331?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3080304736738283331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3080304736738283331' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3080304736738283331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3080304736738283331'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/test_14.html' title='Pretty code'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-8pGAsqMs4wo/TkhNH2fkVtI/AAAAAAAABtY/5stNs_wF828/s72-c/Screen%2BShot%2B2011-08-14%2Bat%2B6.32.32%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-5703504520382619445</id><published>2011-08-14T10:43:00.005-04:00</published><updated>2011-08-15T13:28:21.807-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>Trying Ubuntu Linux (5)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;The project I had yesterday (&lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-4.html"&gt;here&lt;/a&gt;) was to set up my server (Apache) in Linux under VirtualBox so that it is visible from the host (OS X Lion).  I solved that eventually by sticking with NAT mode and issuing this command in Terminal (with Ubuntu powered down):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;VBoxManage modifyvm Ubuntu --natpf1 "server,tcp,,8080,,8080"&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This is exactly what the docs say to do.  The extra twist was to modify &lt;code&gt;/etc/apache2/ports.conf&lt;/code&gt; to add:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;NameVirtualHost *:8080&lt;br /&gt;Listen 8080&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and to modify &lt;code&gt;/etc/apache2/sites-available/default&lt;/code&gt;.  I basically duplicated the whole &lt;code&gt;&amp;lt;VirtualHost&lt;/code&gt; entry and changed the second part to read:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;VirtualHost *:8080&gt;&lt;/code&gt;&lt;br /&gt;..&lt;br /&gt;&lt;br /&gt;And now it works.  From the host in Safari or using curl in Terminal:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;http://127.0.0.1:8080/cgi-bin/test.py&lt;br /&gt;&lt;br /&gt;SERVER_SOFTWARE Apache/2.2.17 (Ubuntu)&lt;br /&gt;SCRIPT_NAME /cgi-bin/test.py&lt;br /&gt;SERVER_SIGNATURE&lt;br /&gt;Apache/2.2.17 (Ubuntu) Server at localhost Port 8080&lt;br /&gt;REQUEST_METHOD GET&lt;br /&gt;SERVER_PROTOCOL HTTP/1.1&lt;br /&gt;QUERY_STRING&lt;br /&gt;..&lt;br /&gt;HTTP_USER_AGENT Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7) AppleWebKit/534.48.3 (KHTML, like Gecko) Version/5.1 Safari/534.48.3&lt;br /&gt;HTTP_CONNECTION keep-alive&lt;br /&gt;SERVER_NAME localhost&lt;br /&gt;..&lt;br /&gt;SERVER_PORT 8080&lt;br /&gt;..&lt;br /&gt;SERVER_ADMIN webmaster@localhost&lt;br /&gt;HTTP_HOST localhost:8080&lt;br /&gt;REQUEST_URI /cgi-bin/test.py&lt;br /&gt;HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;br /&gt;GATEWAY_INTERFACE CGI/1.1&lt;br /&gt;..&lt;br /&gt;HTTP_ACCEPT_LANGUAGE en-us&lt;br /&gt;HTTP_ACCEPT_ENCODING gzip, deflate&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The other thing I've done today is to install EMBOSS and PyCogent.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo apt-get install emboss&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;How easy is that!  The rebase files are at&lt;br /&gt;&lt;br /&gt;&lt;code&gt;http://rebase.neb.com/rebase/rebase.files.html&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;We want # 5 and # 31 as &lt;a href="http://telliott99.blogspot.com/search/label/EMBOSS"&gt;described&lt;/a&gt;.  &lt;code&gt;chmod&lt;/code&gt; for the EMBOSS directories so we can write there:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo chmod 777 -R /usr/share/EMBOSS&lt;br /&gt;rebaseextract&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;tell it where the files are, and it'll do its thing.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;head -5 /usr/share/EMBOSS/data/REBASE/embossre.enz &gt; cat&lt;br /&gt;&lt;br /&gt;# REBASE enzyme patterns for EMBOSS&lt;br /&gt;#&lt;br /&gt;# Format:&lt;br /&gt;# name&lt;ws&gt;pattern&lt;ws&gt;len&lt;ws&gt;ncuts&lt;ws&gt;blunt&lt;ws&gt;c1&lt;ws&gt;c2&lt;ws&gt;c3&lt;ws&gt;c4&lt;br /&gt;#&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;put a sequence file DA19.txt on the Desktop&lt;br /&gt;&lt;br /&gt;&lt;code&gt;remap -sequence DA19.txt&lt;br /&gt;&lt;br /&gt;DA19&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                                                SgeI&lt;br /&gt;                                                | PcsI&lt;br /&gt;                                     SgeI       | SgeI &lt;br /&gt;                   Cac8I             | NspI     | | SgeI     HindIII&lt;br /&gt;                   | PcsI Cac8I      | SgeI     | | | SgeI   |   Cac8I&lt;br /&gt;                   \ \    \          \ \        \ \ \ \      \   \&lt;br /&gt;          GACGAACGCTGGCGGCGTGCTTAACACATGCAAGTCGAACGGAGCGAATGAAAGCTTGCT&lt;br /&gt;&lt;br /&gt;..&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;[ UPDATE:  Something wrong with the formatting here.  The HindIII site, AAGCTT, is at the far right.  ]&lt;br /&gt;&lt;br /&gt;Get Cython:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo apt-get install cython&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Get Pycogent from &lt;code&gt;http://sourceforge.net/projects/pycogent/&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;tar -xzvf ~/Downloads/PyCogent-1.5.1.tgz&lt;br /&gt;python setup.py build&lt;br /&gt;sudo python setup.py install&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I tested Pocogent by downloading sequences and making a phylogenetic tree as described &lt;a href="http://telliott99.blogspot.com/2009/12/pycogent-12-simple-phylogenetic-tree.html"&gt;here&lt;/a&gt; (I had to install a MUSCLE binary &lt;a href="http://www.drive5.com/muscle/downloads.htm"&gt;first&lt;/a&gt;).  I pasted the source into four scripts.&lt;br /&gt;&lt;br /&gt;Not exactly as before, but it looks reasonable.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-R5xSWDB403I/TkfhjImRw2I/AAAAAAAABtQ/IwZbRMzl-yg/s1600/Screen%2BShot%2B2011-08-14%2Bat%2B7.53.14%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://3.bp.blogspot.com/-R5xSWDB403I/TkfhjImRw2I/AAAAAAAABtQ/IwZbRMzl-yg/s320/Screen%2BShot%2B2011-08-14%2Bat%2B7.53.14%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5640725052024537954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-5703504520382619445?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/5703504520382619445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=5703504520382619445' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5703504520382619445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/5703504520382619445'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-5.html' title='Trying Ubuntu Linux (5)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-R5xSWDB403I/TkfhjImRw2I/AAAAAAAABtQ/IwZbRMzl-yg/s72-c/Screen%2BShot%2B2011-08-14%2Bat%2B7.53.14%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3511582816259040356</id><published>2011-08-13T08:44:00.003-04:00</published><updated>2011-08-15T13:28:21.808-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>Trying Ubuntu Linux (4)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;As discussed in previous posts (&lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-1.html"&gt;here&lt;/a&gt;, &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-2.html"&gt;here&lt;/a&gt;, &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-3.html"&gt;here&lt;/a&gt;), I have Ubuntu Linux 11.0.4 running under VirtualBox 4.1.0 on my Powerbook with the host running OS X Lion 10.7 (in a second partition, actually).  I set up and tested Apache Server 2.2 on the guest.  Now I'd like to access the guest server from the host machine, and later the other machines on my Wi-Fi network.  I haven't yet succeeded, so yesterday I asked a question on StackOverflow, which got moved by someone to a related site, "serverfault" (&lt;a href="http://serverfault.com/questions/300668/access-guest-os-server-under-virtualbox?s=514e64b8-ab73-499b-84df-f42951b9beeb"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I got a couple of good suggestions, but didn't yet solve my problem.  However, there are a bunch of "related questions" in the sidebar that look promising.  Time to be (even more) systematic.&lt;br /&gt;&lt;br /&gt;The VirtualBox manual (&lt;a href="http://www.virtualbox.org/manual/ch06.html"&gt;here&lt;/a&gt;) has a section:  &lt;b&gt;Configuring port forwarding with NAT.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So it's pretty clear that we could stay with NAT.  In that case we need to do "port forwarding," although other people have suggested using "bridged mode."  In the NAT method, we simply instruct the VM (as we would a router) that packets arriving on certain ports should be "forwarded to the guest, on the same or a different port."  The manual says to do this from the command line in the host (the first line is their template, the second my implementation):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;VBoxManage modifyvm "VM name" --natpf1 "guestssh,tcp,,2222,,22"&lt;br /&gt;VBoxManage modifyvm Ubuntu --natpf1 "apache,tcp,,8888,,80"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;There are six fields in the last argument:  a name, which is "purely descriptive", the protocol for forwarding, and then two sets of an ip address and port.  So, this example "forwards all TCP traffic arriving on the localhost interface (127.0.0.1) via port 2222 to port 22 in the guest":&lt;br /&gt;&lt;code&gt;&lt;br /&gt;VBoxManage modifyvm "VM name" --natpf1 "guestssh,tcp,127.0.0.1,2222,,22"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;From the docs&lt;br /&gt;&lt;blockquote&gt;Forwarding host ports &lt; 1024 impossible:&lt;br /&gt;On Unix-based hosts (e.g. Linux, Solaris, Mac OS X) it is not possible to bind to ports below 1024 from applications that are not run by root. As a result, if you try to configure such a port forwarding, the VM will refuse to start.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;So that's why we used 8888.  Under Port Forwarding we forward (in the second example) from the host port 8888 to the guest port 80.&lt;br /&gt;&lt;br /&gt;I used the GUI to set this.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-EnLI7ds6u4U/TkZyxPzOASI/AAAAAAAABtI/Mt4nwbDZt1I/s1600/Screen%2BShot%2B2011-08-13%2Bat%2B8.07.18%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 50px;" src="http://3.bp.blogspot.com/-EnLI7ds6u4U/TkZyxPzOASI/AAAAAAAABtI/Mt4nwbDZt1I/s320/Screen%2BShot%2B2011-08-13%2Bat%2B8.07.18%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5640321773708640546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-WsF44sxZMFQ/TkZywyJZhoI/AAAAAAAABtA/jZYurCFSR6U/s1600/Screen%2BShot%2B2011-08-13%2Bat%2B8.07.44%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 264px;" src="http://1.bp.blogspot.com/-WsF44sxZMFQ/TkZywyJZhoI/AAAAAAAABtA/jZYurCFSR6U/s320/Screen%2BShot%2B2011-08-13%2Bat%2B8.07.44%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5640321765748606594" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I believe we should not have to do the command line version.  Just to be safe, I remove the forwarding rule I set when playing around, by doing this from the command line:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;VBoxManage modifyvm Ubuntu --natpf1 delete "apache"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And then repeated setting up forwarding in the GUI (Settings &gt; Network).  To be sure that everybody has got the word, we:&lt;br /&gt;&lt;br /&gt;Quit Ubuntu&lt;br /&gt;Restart VirtualBox&lt;br /&gt;Restart Ubuntu&lt;br /&gt;Restart Apache with:  &lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo /etc/init.d/apache2 restart&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;But it doesn't work.  From the guest, I point Firefox at localhost or 127.0.0.1 and I can see the index page or run my scripts.  Note that this works even though the Apache restart gave this message:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;But from Safari on the host with the same ip address I get "Safari can't connect to the server" and if I add the port (127.0.0.1:8888) it just hangs.  127.0.1.1 also doesn't work.&lt;br /&gt;&lt;br /&gt;Now, what could be wrong?  From serverfault (&lt;a href="http://serverfault.com/questions/300668/access-guest-os-server-under-virtualbox?s=514e64b8-ab73-499b-84df-f42951b9beeb"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;Iain says to try bridged mode.&lt;br /&gt;&lt;br /&gt;I tested that early on but it didn't make any difference.  Also, the docs clearly say that NAT should work.  I'll have to test some more, but first..&lt;br /&gt;&lt;br /&gt;Eric Fortis says:  &lt;br /&gt;&lt;br /&gt;"then from the host PC browser access the IP of the Ubuntu virtual machine, instead of 127.0.0.1. ifconfig will show you your IP."&lt;br /&gt;&lt;code&gt;&lt;br /&gt;te@VB:~$ ifconfig&lt;br /&gt;eth0      Link encap:Ethernet  HWaddr 08:00:27:88:33:a4  &lt;br /&gt;          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0&lt;br /&gt;          inet6 addr: fe80::a00:27ff:fe88:33a4/64 Scope:Link&lt;br /&gt;          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1&lt;br /&gt;          RX packets:122 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;          TX packets:182 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;          collisions:0 txqueuelen:1000 &lt;br /&gt;          RX bytes:43296 (43.2 KB)  TX bytes:23263 (23.2 KB)&lt;br /&gt;&lt;br /&gt;lo        Link encap:Local Loopback  &lt;br /&gt;          inet addr:127.0.0.1  Mask:255.0.0.0&lt;br /&gt;          inet6 addr: ::1/128 Scope:Host&lt;br /&gt;          UP LOOPBACK RUNNING  MTU:16436  Metric:1&lt;br /&gt;          RX packets:18 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;          collisions:0 txqueuelen:0 &lt;br /&gt;          RX bytes:1642 (1.6 KB)  TX bytes:1642 (1.6 KB)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If I'm reading this correctly, the second entry is for "local loopback", that is, it doesn't go through the virtual network card.  And the first one uses eth0.  So that might make a difference (Ethernet v. Wi-Fi)&lt;br /&gt;&lt;br /&gt;Also, the ip address is 10.0.2.15, which I think should not be visible beyond the "router"---the VM.&lt;br /&gt;&lt;br /&gt;The third comment is from anthonysomerset: &lt;br /&gt;&lt;br /&gt; is apache in your vhost configured to listen on the correct ports? this will work in bridged or nat mode, also check any firewall rules in the guest and that network access works out of the guest as well.&lt;br /&gt;&lt;br /&gt;So:&lt;br /&gt;- this will work in bridged or NAT&lt;br /&gt;- make sure the Listen directive is correct&lt;br /&gt;- check the firewall&lt;br /&gt;- check that network access works out of the guest&lt;br /&gt;&lt;br /&gt;The guest is set up to listen on port 80.  That is the standard port set up in Apache.  I wrote a Python script to filter comments (filter.py) and do:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python filter.py /etc/apache2/apache2.conf&lt;br /&gt;&lt;br /&gt;Include mods-enabled/*.load&lt;br /&gt;Include mods-enabled/*.conf&lt;br /&gt;Include httpd.conf&lt;br /&gt;Include ports.conf&lt;br /&gt;..&lt;br /&gt;Include conf.d/&lt;br /&gt;Include sites-enabled/&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So there are lots of places to look for possible conflicts!  Luckily, httpd.conf is empty.  ports.conf:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;..&lt;br /&gt;NameVirtualHost *:80&lt;br /&gt;Listen 80&lt;br /&gt;..&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I'm not quite sure about the first &lt;a href="http://httpd.apache.org/docs/2.0/mod/core.html#page-header"&gt;one&lt;/a&gt;, but the Listen part is correct.&lt;br /&gt;&lt;br /&gt;Firewall rules are here (at least, some are):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;te@VB:/etc/apache2/sites-available$ python ~/Desktop/filter.py default&lt;br /&gt;&amp;lt;VirtualHost *:80&gt;&lt;br /&gt;	ServerAdmin webmaster@localhost&lt;br /&gt;	DocumentRoot /var/www&lt;br /&gt;	&amp;lt;Directory /&gt;&lt;br /&gt;		Options FollowSymLinks&lt;br /&gt;		AllowOverride None&lt;br /&gt;	&amp;lt;/Directory&gt;&lt;br /&gt;	&amp;lt;Directory /var/www/&gt;&lt;br /&gt;		Options Indexes FollowSymLinks MultiViews&lt;br /&gt;		AllowOverride None&lt;br /&gt;		Order allow,deny&lt;br /&gt;		Allow from all&lt;br /&gt;		# Allow from 127.0.0.0/255.0.0.0 ::1/128&lt;br /&gt;	&amp;lt;/Directory&gt;&lt;br /&gt;..&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Skipping the script stuff, this has been edited from my previous rule restricting access to go back to Allow from all.  &lt;br /&gt;&lt;br /&gt;About checking network access from the guest:  if he means accessing a server on the host machine, I haven't tried that yet.  But of course, Firefox works.&lt;br /&gt;&lt;br /&gt;So, out of all this, the only thing I can see is that I don't know what this stuff is about.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;NameVirtualHost *:80&lt;br /&gt;&amp;lt;VirtualHost *:80&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I tried switching from Wi-Fi to Ethernet in the host, but that didn't help.&lt;br /&gt;&lt;br /&gt;I'm going to have to look through all the other posts related to this topic.  But it seems like it's getting to be too hard, after all, I used VirtualBox to make things easy.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3511582816259040356?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3511582816259040356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3511582816259040356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3511582816259040356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3511582816259040356'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-4.html' title='Trying Ubuntu Linux (4)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-EnLI7ds6u4U/TkZyxPzOASI/AAAAAAAABtI/Mt4nwbDZt1I/s72-c/Screen%2BShot%2B2011-08-13%2Bat%2B8.07.18%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1537133407173035484</id><published>2011-08-13T07:36:00.001-04:00</published><updated>2011-08-13T07:41:42.913-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Keeping up appearances</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Something's changed in blogger that messes with my code examples.  The last normal &lt;a href="http://telliott99.blogspot.com/2011/08/pymol-1.html"&gt;one&lt;/a&gt; is from Sat August 6, and the first unusual &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-2.html"&gt;one&lt;/a&gt; is from last Thu August 11.  It looks the same as ever in Preview mode, but after publishing, all the code text has acquired an extra newline and is double-spaced.&lt;br /&gt;&lt;br /&gt;Code is enclosed within tags:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&amp;lt;table bgcolor="#ffffb0" border="0" &lt;br /&gt;  width="100%" padding="4"&gt;&lt;br /&gt;&amp;lt;tbody&gt;&lt;br /&gt;&amp;lt;tr&gt;&lt;br /&gt;&amp;lt;d&gt;&lt;br /&gt;&amp;lt;pre style=" hidden;font-family:monaco;"&gt;&lt;br /&gt;..&lt;br /&gt;&amp;lt;/pre&gt;&lt;br /&gt;&amp;lt;/table&gt;&lt;br /&gt;&amp;lt;/div&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I liked this method because the output is monospaced, and the background colored according to the type of code (Python, R, output, etc).&lt;br /&gt;&lt;br /&gt;I guess I'll have to look into CSS.  If anyone has a good set of instructions to point me to, I'd be grateful.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1537133407173035484?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1537133407173035484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1537133407173035484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1537133407173035484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1537133407173035484'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/keeping-up-appearances.html' title='Keeping up appearances'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-6213980550726940716</id><published>2011-08-12T08:30:00.005-04:00</published><updated>2011-08-13T07:36:00.296-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>Python C Extension</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Following Andrew Dalke's example, this is perhaps the simplest possible C extension for Python.  For explanation of what's happening, see his &lt;a href="http://www.dalkescientific.com/writings/NBN/c_extensions.html"&gt;page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[  Something's gone wacko with this post---it's single spaced in preview, double after posting  ]&lt;br /&gt;&lt;br /&gt;&lt;code&gt;x.c&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;#include &amp;lt;math.h&gt;&lt;br /&gt;#include "Python.h"&lt;br /&gt;&lt;br /&gt;int process (const char *c, double f) {&lt;br /&gt;    int i = 0;&lt;br /&gt;    if (c[0] == 'c') {&lt;br /&gt;        i = floor(f);&lt;br /&gt;    }&lt;br /&gt;    return i;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PyDoc_STRVAR(x__doc__,&lt;br /&gt;"x module for process'ing stuff");&lt;br /&gt;&lt;br /&gt;PyDoc_STRVAR(process__doc__,&lt;br /&gt;"c,f -&gt; do something with f if c == 'c'");&lt;br /&gt;&lt;br /&gt;static PyObject *&lt;br /&gt;py_process(PyObject *self, PyObject *args) {&lt;br /&gt;    double f = 0;&lt;br /&gt;    char *c;&lt;br /&gt;    int i;&lt;br /&gt;    if (!PyArg_ParseTuple(args, "sd:process", &amp;c, &amp;f))&lt;br /&gt;    		return NULL; &lt;br /&gt;    i = process(c,f);&lt;br /&gt;    return PyInt_FromLong((long) i);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static PyMethodDef x_methods[] = {&lt;br /&gt;	{"process",  py_process, METH_VARARGS, process__doc__},&lt;br /&gt;	{NULL, NULL}      /* sentinel */&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;PyMODINIT_FUNC&lt;br /&gt;initx(void)&lt;br /&gt;{&lt;br /&gt;	Py_InitModule3("x", x_methods, x__doc__);&lt;br /&gt;}&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;setup.py&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;from distutils.core import setup, Extension&lt;br /&gt;&lt;br /&gt;setup(name="x", version="0.0",&lt;br /&gt;	ext_modules = [Extension("x", ["x.c"])])&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python setup.py build&lt;br /&gt;running build&lt;br /&gt;running build_ext&lt;br /&gt;building 'x' extension&lt;br /&gt;creating build&lt;br /&gt;creating build/temp.macosx-10.6-universal-2.6&lt;br /&gt;gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -DNDEBUG -g -fwrapv -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch ppc -arch x86_64 -pipe -I/System/Library/Frameworks/Python.framework/Versions/2.6/include/python2.6 -c x.c -o build/temp.macosx-10.6-universal-2.6/x.o&lt;br /&gt;creating build/lib.macosx-10.6-universal-2.6&lt;br /&gt;gcc-4.2 -Wl,-F. -bundle -undefined dynamic_lookup -arch i386 -arch ppc -arch x86_64 build/temp.macosx-10.6-universal-2.6/x.o -o build/lib.macosx-10.6-universal-2.6/x.so&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;You can control which architecture is build via &lt;code&gt;setup.py&lt;/code&gt; with:&lt;br /&gt; &lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;export ARCHFLAGS="-arch x86_64"&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; ln -s build/lib.macosx-10.6-universal-2.6/x.so x.so&lt;br /&gt;&gt;&lt;br /&gt;&gt; python -c "import math;  import x;  print x.process('c',math.pi)"&lt;br /&gt;3&lt;br /&gt;&gt; python -c "import math;  import x;  print x.process('a',math.pi)"&lt;br /&gt;0&lt;br /&gt;&gt; python&lt;br /&gt;Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) &lt;br /&gt;[GCC 4.2.1 (Apple Inc. build 5646)] on darwin&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; import x&lt;br /&gt;&gt;&gt;&gt; x.__doc__&lt;br /&gt;"x module for process'ing stuff"&lt;br /&gt;&gt;&gt;&gt; x.process.__doc__&lt;br /&gt;"c,f -&gt; do something with f if c == 'c'"&lt;br /&gt;&gt;&gt;&gt; &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Looks good.&lt;br /&gt;&lt;br /&gt;Note:  on my 64-bit machines I'm getting a warning:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x.c: In function ‘process’:&lt;br /&gt;x.c:7: warning: implicit conversion shortens 64-bit value into a 32-bit value&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Converting i to &lt;code&gt;long&lt;/code&gt; doesn't help.  I'll try to look into that.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-6213980550726940716?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/6213980550726940716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=6213980550726940716' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6213980550726940716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6213980550726940716'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/python-c-extension.html' title='Python C Extension'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-6526380975061418621</id><published>2011-08-12T08:00:00.001-04:00</published><updated>2011-08-15T13:28:21.810-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>Trying Ubuntu Linux (3)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I have an idea that someday I might try to teach students how to set up a web site (for example, &lt;a href="http://emboss.sourceforge.net/"&gt;EMBOSS&lt;/a&gt; on a local network would be nice).  Python would be a perfect fit and it should be fun and extensible.  I would probably want a neutral platform to do that (since most would be trained on Windows and I know nothing except OS X), so I looked into adding Apache Server to my Ubuntu 11.0.4 Desktop install (posts &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-1.html"&gt;here&lt;/a&gt; and &lt;a href="http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-2.html"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;There is a nice guide on the web from Ubuntu (&lt;a href="https://help.ubuntu.com/10.04/serverguide/C/index.html"&gt;here&lt;/a&gt;), and some simple instructions are &lt;a href="http://www.danscourses.com/Linux-Fundamentals/how-to-install-apache-php-mysql-and-phpmyadmin-in-ubuntu-385.html"&gt;here&lt;/a&gt;, and the Apache docs are &lt;a href="http://httpd.apache.org/docs/current/"&gt;here&lt;/a&gt;.  I could have started by grabbing the Server version of Ubuntu, but instead I did:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get install apache2&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;As easy as that.  Start and stop commands:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo /etc/init.d/apache2 start&lt;br /&gt;sudo /etc/init.d/apache2 stop&lt;br /&gt;sudo /etc/init.d/apache2 restart&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;To test it, just use Firefox and point it at &lt;code&gt;localhost&lt;/code&gt; or &lt;code&gt;127.0.0.1&lt;/code&gt;.  The index page is at &lt;code&gt;/var/www/index.html&lt;/code&gt; (the "document root" is &lt;code&gt;/var/www&lt;/code&gt;).  If you want to get a little fancier, you can grab PHP:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get install php5 libapache2-mod-php5&lt;br /&gt;sudo /etc/init.d/apache2 restart&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And put this in &lt;code&gt;/var/www/test.php&lt;/code&gt;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;lt;?php phpinfo(); ?&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Go to &lt;code&gt;localhost/test.php&lt;/code&gt; and it should print a bunch of details about your setup.&lt;br /&gt;&lt;br /&gt;I spent a lot of time working on access control (Apache docs &lt;a href="http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#deny"&gt;here&lt;/a&gt;).  I should probably have read the VirtualBox guide first (&lt;a href="http://www.virtualbox.org/manual/ch06.html#network_nat"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;blockquote&gt;A virtual machine with NAT enabled acts much like a real computer that connects to the Internet through a router. The "router", in this case, is the VirtualBox networking engine, which maps traffic from and to the virtual machine transparently. The disadvantage of NAT mode is that, much like a private network behind a router, the virtual machine is invisible and unreachable from the outside internet; you cannot run a server this way unless you set up port forwarding (described below).&lt;/blockquote&gt;&lt;br /&gt;Actually, we will want to do this later.  A lot of time was wasted because I followed the "simple" instructions (e.g. Apache's) and couldn't figure out why stuff didn't work.&lt;br /&gt;&lt;br /&gt;It turns out that although &lt;code&gt;/etc/apache2/apache2.conf&lt;/code&gt; and &lt;code&gt;/etc/apache2/httpd.conf&lt;/code&gt; have relevant settings there are a bunch of other files (in directories under &lt;code&gt;/etc/apache2/&lt;/code&gt;).  If you want to change access to the document root or scripts, you have to modify &lt;code&gt;/etc/apache2/sites-available/default&lt;/code&gt;.  Guess I should have read the first page (&lt;a href="https://help.ubuntu.com/10.04/serverguide/C/httpd.html"&gt;here&lt;/a&gt;) of the Ubuntu Server docs.  It's right there!&lt;br /&gt;&lt;br /&gt;Here is part of the file in the original form:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;	ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/&lt;br /&gt;	&amp;lt;Directory "/usr/lib/cgi-bin"&gt;&lt;br /&gt;		AllowOverride None&lt;br /&gt;		Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch&lt;br /&gt;		Order allow,deny&lt;br /&gt;		Allow from all&lt;br /&gt;	&amp;lt;/Directory&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I'm not sure what all of this does, but using ScriptAlias means that (Apache &lt;a href="http://httpd.apache.org/docs/current/howto/cgi.html"&gt;docs&lt;/a&gt; again):&lt;br /&gt;&lt;blockquote&gt;The ScriptAlias directive tells Apache that a particular directory is set aside for CGI programs. Apache will assume that every file in this directory is a CGI program, and will attempt to execute it, when that particular resource is requested by a client.&lt;/blockquote&gt;&lt;br /&gt;I just modified &lt;code&gt;/usr/lib/cgi-bin/&lt;/code&gt; to be &lt;code&gt;/home/te/cgi-bin/&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;And, since we will ultimately care about access permissions, you should read (at least) this &lt;a href="http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#deny"&gt;page&lt;/a&gt; of the docs, which explains that &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;		Order allow,deny&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;is explained as:&lt;br /&gt;&lt;blockquote&gt;Allow,Deny&lt;br /&gt;First, all Allow directives are evaluated; at least one must match, or the request is rejected. Next, all Deny directives are evaluated. If any matches, the request is rejected. Last, any requests which do not match an Allow or a Deny directive are denied by default.&lt;br /&gt;Deny,Allow&lt;br /&gt;First, all Deny directives are evaluated; if any match, the request is denied unless it also matches an Allow directive. Any requests which do not match any Allow or Deny directives are permitted.&lt;/blockquote&gt;&lt;br /&gt;I copied from further down in the file (about access to &lt;code&gt;/usr/share/docs&lt;/code&gt;) to the ScriptAlias directive above:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;        Order deny,allow&lt;br /&gt;        Deny from all&lt;br /&gt;        Allow from 127.0.0.0/255.0.0.0 ::1/128&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The subnet masking stuff will need an explanation of its own.&lt;br /&gt;&lt;br /&gt;So now, I can put the first script from the second part of this &lt;a href="http://telliott99.blogspot.com/2010/11/simple-server-running-python-script-on_16.html"&gt;post&lt;/a&gt; (that prints data from &lt;code&gt;os.environ&lt;/code&gt; in &lt;code&gt;cgi-bin&lt;/code&gt; under my home directory, and it works.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-6526380975061418621?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/6526380975061418621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=6526380975061418621' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6526380975061418621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/6526380975061418621'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-3.html' title='Trying Ubuntu Linux (3)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-4457915615986396710</id><published>2011-08-11T16:04:00.004-04:00</published><updated>2011-08-15T13:28:21.811-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>Trying Ubuntu Linux (2)</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/-hsHaaOn95BY/TkQ4D5Ls7wI/AAAAAAAABs4/SCZV5s9J6Yg/s1600/Screen%2BShot%2B2011-08-11%2Bat%2B4.00.30%2BPM.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 305px; height: 320px;" src="http://2.bp.blogspot.com/-hsHaaOn95BY/TkQ4D5Ls7wI/AAAAAAAABs4/SCZV5s9J6Yg/s320/Screen%2BShot%2B2011-08-11%2Bat%2B4.00.30%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5639694272915369730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I'm installing software on Ubuntu 11.0.4 (in a Virtual Box VM running under OS X Lion) and my standard test is &lt;code&gt;matplotlib&lt;/code&gt;.  To begin with, Ubuntu 11.0 has &lt;code&gt;python&lt;/code&gt; but does not have &lt;code&gt;numpy&lt;/code&gt;.  So, let's start there.&lt;br /&gt;&lt;br /&gt;I found build instructions &lt;a href="http://www.scipy.org/Installing_SciPy/Linux"&gt;here&lt;/a&gt;, but didn't actually follow them.  Instead, I took their advice and used &lt;code&gt;apt-get&lt;/code&gt;.  While I was still thinking I would build everything I did:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get install gfortran&lt;br /&gt;sudo apt-get install python-dev&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And then I went after BLAS, and LAPACK.  Based on the library name on this &lt;a href="https://launchpad.net/ubuntu/natty/+source/blas"&gt;page&lt;/a&gt;, I did:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get install libblas3gf&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And using the library name from this &lt;a href="https://launchpad.net/ubuntu/+source/lapack/3.3.0-3/+build/2227589"&gt;page&lt;/a&gt;, I did:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get install liblapack3gf&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Then, I just did:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get install python-numpy&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And, amazingly enough, it works:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;gt;&amp;gt;&amp;gt; import numpy&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Now:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get install zlib-bin&lt;br /&gt;sudo apt-get install libpng3&lt;br /&gt;sudo apt-get install libfreetype6&lt;br /&gt;sudo apt-get install python-matplotlib&lt;br /&gt;Failed to fetch http://us.archive.ubuntu.com/ubuntu/pool/main/t/tcl8.5/tcl8.5_8.5.9-2_amd64.deb  Something wicked happened resolving 'us.archive.ubuntu.com:http' (-5 - No address associated with hostname)&lt;br /&gt;E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Oops..&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sudo apt-get update&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And now it gets tcl8.5&lt;br /&gt;&lt;br /&gt;What else to do for matplotlib?&lt;br /&gt;Nothing!&lt;br /&gt;&lt;br /&gt;We'll try the example from &lt;a href="http://telliott99.blogspot.com/2010/02/plotting-normal-distribution-with.html"&gt;here&lt;/a&gt;, and we get a png in the right place, which I just double click and get the graphic at the top.  Here is the whole Desktop:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-yvVapv2fGCQ/TkQ4D2GAh8I/AAAAAAAABsw/VtnfUc6YYQ4/s1600/Screen%2BShot%2B2011-08-11%2Bat%2B4.00.06%2BPM.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 274px;" src="http://2.bp.blogspot.com/-yvVapv2fGCQ/TkQ4D2GAh8I/AAAAAAAABsw/VtnfUc6YYQ4/s320/Screen%2BShot%2B2011-08-11%2Bat%2B4.00.06%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5639694272086181826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I really can't take any credit for this.  I am &lt;del&gt;very impressed&lt;/del&gt; speechless with the Ubuntu dev guys.&lt;br /&gt;&lt;br /&gt;[ UPDATE:  Did the same &lt;code&gt;apt-get&lt;/code&gt; for scipy and the test at the bottom of this &lt;a href="http://telliott99.blogspot.com/2010/02/playing-with-scipy-install-part-3.html"&gt;post&lt;/a&gt; works too! ]&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-4457915615986396710?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/4457915615986396710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=4457915615986396710' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4457915615986396710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4457915615986396710'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-2.html' title='Trying Ubuntu Linux (2)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-hsHaaOn95BY/TkQ4D5Ls7wI/AAAAAAAABs4/SCZV5s9J6Yg/s72-c/Screen%2BShot%2B2011-08-11%2Bat%2B4.00.30%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-2920256099246200213</id><published>2011-08-11T08:00:00.000-04:00</published><updated>2011-08-15T13:28:21.812-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>Trying Ubuntu Linux (1)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I thought I would play around with Linux a bit, trying to improve my Unix skills.  I'm running it in a second partition on my Macbook that has OS X Lion installed (post &lt;a href="http://telliott99.blogspot.com/2011/07/os-x-lion.html"&gt;here&lt;/a&gt;) and runs a Virtual Box VM.&lt;br /&gt;&lt;br /&gt;I first heard about and tried Oracle's &lt;a href="http://www.virtualbox.org/"&gt;Virtual Box&lt;/a&gt; in connection with &lt;a href="http://qiime.org"&gt;QIIME&lt;/a&gt; (post &lt;a href="http://telliott99.blogspot.com/2011/02/qiime-1.html"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I grabbed a VirtualBox version 4.1 binary installer for Mac OS X &lt;a href="http://www.virtualbox.org/wiki/Downloads"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Then I downloaded Ubuntu Linux 11.04 (now why is it called &lt;a href="https://wiki.ubuntu.com/NattyNarwhal"&gt;Natty Narwhal&lt;/a&gt;?) from &lt;a href="http://releases.ubuntu.com/natty/"&gt;here&lt;/a&gt;.  There is another download page &lt;a href="http://www.ubuntu.com/download/ubuntu/download"&gt;here&lt;/a&gt; but I think it has the same choices.&lt;br /&gt;&lt;br /&gt;I ended up trying &lt;i&gt;both&lt;/i&gt; Desktop "CD"s, because I was a little confused about the version I needed.  There appears to be only 32-bit for i386 (&lt;code&gt;ubuntu-11.04-desktop-i386.iso&lt;/code&gt;) but 64-bit for AMD (&lt;code&gt;ubuntu-11.04-desktop-amd64.iso&lt;/code&gt;).  However, the chip running the host OS is not relevant.  The QIIME Linux is labeled AMD64 and is 64-bit and can &lt;a href="http://qiime.org/install/virtual_box.html"&gt;run&lt;/a&gt; on my 64-bit machines under a VM.  I suppose it would matter if I wanted to run Linux directly in the partition instead of in Virtual Box.&lt;br /&gt;&lt;br /&gt;I have to confess, I've installed several different Linux versions (and then removed them) and the one described here a number of times, because I ran into problems with the install that I couldn't figure out how to back out of.  But experimentation is relatively cheap, since it's just a VM.  I don't have any worries about leftover crap on my disk.  If worst comes to worst I can just erase the whole partition.  Although it takes patience for the install steps.&lt;hr&gt;&lt;br /&gt;&lt;h4&gt;Stock 64-bit Ubuntu Linux&lt;/h4&gt;&lt;br /&gt;So, I ran the Virtual Box installer, set the Name as Ubuntu, Operating System as Linux and the Version as Ubuntu 64.  Then I set up the VM with all standard options (except 1 GB for RAM).  Just click on through.&lt;br /&gt;&lt;br /&gt;To actually install Linux using a &lt;code&gt;.iso&lt;/code&gt; file, use the "First Run Wizard" by double-clicking the new machine in the list.  For Select Installation Media:  I navigated to the saved file.  On one try I somehow got past the Wizard without properly installing and had to delete and re-configure the VM.&lt;br /&gt;&lt;br /&gt;It takes quite a while to boot the first time, copying all the files over to the VM, I guess.  Choose Erase disk and install Ubuntu (the disk size should be only the size of the VM disk).  There are a bunch of dialogs to go through.  After the install and reboot we get a message that Unity won't run on our hardware and so we're going to get Classic.  Oh well.&lt;br /&gt;&lt;br /&gt;Reboot..&lt;br /&gt;&lt;br /&gt;Now, there are two things that seem really important to have but are not present in this stock install:&lt;br /&gt;&lt;br /&gt;• a Shared Folder for file sharing between host and guest OS&lt;br /&gt;• a Clipboard for copy/paste between host and guest OS&lt;br /&gt;&lt;br /&gt;To have these features you must install what are called the "Guest Additions," which are additions to the Linux kernel.  Some instructions are on this &lt;a href="http://forums.virtualbox.org/viewtopic.php?t=15679"&gt;page&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;After you have installed the Linux Guest system, there are a few additional packages needed for the Guest Additions. These packages enables you to create kernel modules. For Debian and Debian based distro's like Ubuntu, you need the following packages:&lt;br /&gt;dkms&lt;br /&gt;build-essential&lt;br /&gt;linux-headers-generic&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Find the Terminal (why not just drag it to the menu bar) and do:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo apt-get install dkms build-essential linux-headers-generic&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You'll have to type in the command, since copy/paste doesn't work yet  :)&lt;br /&gt;When it's done:&lt;br /&gt;&lt;br /&gt;Reboot to make the changes effective..&lt;br /&gt;&lt;br /&gt;Next, "mount" the Guest Additions "iso":  in the VB menu (in OS X) under Devices, choose Install Guest Additions.  It shows up as a CD on the Desktop.  Then from the dialog choose the default that automatically runs the shell script.  Or hit Open AutoRun Prompt &gt; OK and then in Terminal do:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;media/VBOXADDITIONS{version}/VBoxLinuxAdditions.run&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;After it's done, reboot again..&lt;br /&gt;&lt;br /&gt;At this point, copy/paste between host/guest should work.  You'll have to click twice, once to switch focus to the VM and once to switch focus again to whatever application is receiving the paste.&lt;br /&gt;&lt;br /&gt;There are two different key combos for Linux and neither is CMD.  Not sure if this is standard Linux or it is just since the left CMD key is a special key for the VM.  To copy and paste within Terminal on Linux use CTL-SHIFT-x and CTL-SHIFT-v rather than CMD (for Text Edit just use CTL-x and CTL-v).&lt;br /&gt;&lt;br /&gt;Now we can try to get shared folders.  In the Virtual Box window, from the Devices menu choose Shared Folders.  Add a folder (navigate the host OS to the desired path).  Also, make a folder under Linux that we'll use to share with, say &lt;code&gt;/home/telliott/Desktop/share&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In the dialog, choose Automount (and Make Permanent, see below).  Even after the specification of a shared folder, you still have to mount it within Linux.  The Qiime guys do:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo mount -a&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately, it doesn't seem to work for me.  (Not in the Qiime install either).  So then I tried &lt;a href="http://forums.virtualbox.org/viewtopic.php?t=15868"&gt;this&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo mount -t vboxsf -o uid=1000,gid=1000 shared ~/Desktop/share&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The first argument after &lt;code&gt;vboxsf&lt;/code&gt; above is the name of the folder on the host OS (as defined by us in the Devices menu above).  The second argument is the name of the &lt;i&gt;sharepoint&lt;/i&gt; --- the path to a folder on the Guest.&lt;br /&gt;&lt;br /&gt;It didn't work at first, because it turned out, I had failed to check Automount above.  And, if you want to make a change to the Shared Folder setting, it seems that you have to reboot to be able to actually do it, otherwise there's a message about the resource being in use.&lt;br /&gt;&lt;br /&gt;Also, I never did figure out how to change Make Permanent.  Any change or attempt to delete in the Shared Folders dialog (even after a reboot) gives an error message:  VERR_PERMISSION_DENIED.  There's a note in the link about putting the mount command in &lt;br /&gt;&lt;br /&gt;&lt;code&gt;/etc/rc.local&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;but I don't see how that's going to work since it needs to run as root?  Luckily, the VM allows me to suspend Linux in its current state.  And now, thinking that I need to re-run that command every time upon booting, I try it and get:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sudo mount -t vboxsf -o uid=1000,gid=1000 shared ~/Desktop/share&lt;br /&gt;/sbin/mount.vboxsf: mounting failed with the error: Invalid argument&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;After re-boot, the same &lt;code&gt;mount&lt;/code&gt; fails!  I am starting to get angry with this thing.&lt;br /&gt;&lt;br /&gt;I gave up and set up Dropbox access from within the VM.  It works great.&lt;br /&gt;&lt;br /&gt;Now, to build some software.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-2920256099246200213?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/2920256099246200213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=2920256099246200213' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2920256099246200213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2920256099246200213'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/trying-ubuntu-linux-1.html' title='Trying Ubuntu Linux (1)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1349284425694876291</id><published>2011-08-06T17:07:00.010-04:00</published><updated>2011-08-07T12:48:13.384-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>PyMOL (1)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-E7IYbSFHH1Q/Tj2tQ3kXdEI/AAAAAAAABsg/tJZR6UWDRlY/s1600/Screen%2BShot%2B2011-08-06%2Bat%2B4.11.31%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 303px;" src="http://2.bp.blogspot.com/-E7IYbSFHH1Q/Tj2tQ3kXdEI/AAAAAAAABsg/tJZR6UWDRlY/s320/Screen%2BShot%2B2011-08-06%2Bat%2B4.11.31%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5637852813843723330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;If you're interested in Python and bioinformatics you've undoubtedly heard of &lt;a href="http://www.pymol.org/"&gt;Pymol&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you're at a place that cares about molecular biology (my institution does not), you may even have a site license.  I have a copy that I got for educational use about 3 years ago, and still have some examples that I made for a class I taught.  That version has a Cocoa GUI.  &lt;br /&gt;&lt;br /&gt;There is also an open source version that is up on SourceForge (&lt;a href="http://sourceforge.net/projects/pymol/"&gt;here&lt;/a&gt;).  I thought it would be a good challenge to try to build the open source Pymol.  &lt;br /&gt;&lt;br /&gt;[ Update:  I think the Cocoa GUI one is MacPymol &lt;a href="http://sourceforge.net/projects/pymol/files/Legacy/macpymol-0_99rc6.tar.gz/download"&gt;here&lt;/a&gt;).  I just noticed this on the legacy page.  ]&lt;br /&gt;&lt;br /&gt;The dependencies are listed in the README as:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;PyMOL has the following external dependencies:&lt;br /&gt;  1. OpenGL&lt;br /&gt;  2. GLUT library for OpenGL (or freeglut)&lt;br /&gt;  3. Python (v 2.1 or better) compiled with threads support&lt;br /&gt;  4. libpng (can compiled without it, but image saves won't work)&lt;br /&gt;  5. Tcl/Tk (for the external GUI)&lt;br /&gt;  6. Numerical Python (technically optional - now using numpy instead)&lt;br /&gt;  7. Python megawidgets (Pmw -- only required for the "external" GUI)&lt;br /&gt;  8. FreeType2 (if you want nice fonts)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Most of these are already present in Lion, so I didn't think it would be too difficult.  What I failed to realize is that the Tcl/Tk in Lion is apparently messed up (brief SO discussion &lt;a href="http://stackoverflow.com/questions/6781558/why-does-idle-keep-crashing-mac/6781900#6781900"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I downloaded &lt;code&gt;pymol-v1.4.1.tar.bz2&lt;/code&gt; from the main page at SourceForge, and did the standard &lt;code&gt;distutils&lt;/code&gt; thing:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;python setup.py build&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The first error was:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;layer0/ShaderMgr.c:173: error: ‘GLEW_OK’ undeclared (first use in this function)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The top Google &lt;a href="http://glew.sourceforge.net/basic.html"&gt;hit&lt;/a&gt; shows it's related to OpenGL and glut.&lt;br /&gt;If present, there should be a file &lt;code&gt;glew.h&lt;/code&gt; (and likely &lt;code&gt;glut.h&lt;/code&gt;).&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; find /usr -iname *glut*&lt;br /&gt;/usr/X11/include/GL/glut.h&lt;br /&gt;/usr/X11/include/GL/glutf90.h&lt;br /&gt;/usr/X11/lib/libglut.3.7.dylib&lt;br /&gt;/usr/X11/lib/libglut.3.dylib&lt;br /&gt;/usr/X11/lib/libglut.dylib&lt;br /&gt;/usr/X11/lib/pkgconfig/glut.pc&lt;br /&gt;&gt; find /usr -iname *glew*&lt;br /&gt;&gt; find /usr -iname *GLEW*&lt;br /&gt;&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;No glew.&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;brew install glew&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;works and we have &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&lt;br /&gt;$ find /usr/local/lib -iname *glew*&lt;br /&gt;/usr/local/lib/libGLEW.1.5.8.dylib&lt;br /&gt;/usr/local/lib/libGLEW.1.5.dylib&lt;br /&gt;/usr/local/lib/libGLEW.a&lt;br /&gt;/usr/local/lib/libGLEW.dylib&lt;br /&gt;/usr/local/lib/pkgconfig/glew.pc&lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and we find "GLEW_OK defined on line 15273 of glew.h.  Unfortunately, the build fails with a link error at the end:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;ld: warning: ignoring file /usr/local/lib/libGLEW.dylib, file was built for unsupported file format which is not the architecture being linked (i386)&lt;br /&gt;ld: duplicate symbol __CShaderMgr in build/temp.macosx-10.7-intel-2.7/layer2/RepCylBond.o and build/temp.macosx-10.7-intel-2.7/layer2/RepCartoon.o for architecture i386&lt;br /&gt;&lt;br /&gt;&gt; file /usr/local/lib/libGLEW.dylib&lt;br /&gt;/usr/local/lib/libGLEW.dylib: Mach-O 64-bit dynamically linked shared library x86_64&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So it seems that Homebrew has built x86_64, which can't work with what pymol is building (i386).  What I should do is rebuild &lt;code&gt;libGLEW.dylib&lt;/code&gt; with the correct architecture.  I haven't accomplished that yet.  Instead, I noticed a &lt;a href="http://www.mail-archive.com/pymol-users@lists.sourceforge.net/msg09218.html"&gt;page&lt;/a&gt; that discusses this very same problem. One answer is in a different thread (&lt;a href="http://www.mail-archive.com/pymol-users@lists.sourceforge.net/msg09074.html"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Kasper, not sure if this will help you, but I think the GLEW stuff was&lt;br /&gt;added recently in V1.4.x and it seems to be still somewhat experimental.&lt;br /&gt;May be to get you started you could switch to v1.3r1 from the repository&lt;br /&gt;and try to embedd that version. V1.3.x should not contain the new GL&lt;br /&gt;stuff.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So let's try 1.3.  I grabbed &lt;code&gt;pymol-1.3r2-src.tar.bz2&lt;/code&gt; from &lt;a href="http://sourceforge.net/projects/pymol/files/pymol/"&gt;here&lt;/a&gt; and it got past the previous problem but then dies with:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;/usr/X11R6/include/ft2build.h:56:38: error: freetype/config/ftheader.h: No such file or directory&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;It's looking in &lt;code&gt;/usr/X11R6&lt;/code&gt; and can't find freetype which is in /usr/X11 (my post &lt;a href="http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion-revised.html"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;So.. I modify the &lt;code&gt;setup.py&lt;/code&gt; in pymol:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;                     &lt;br /&gt;    inc_dirs=["ov/src",&lt;br /&gt;              "layer0","layer1","layer2",&lt;br /&gt;              "layer3","layer4","layer5", &lt;br /&gt;              "/usr/X11R6/include",&lt;br /&gt;              # my additions &lt;br /&gt;               "/usr/X11/include",&lt;br /&gt;               "/usr/X11/include/freetype2",&lt;br /&gt;               "/usr/local/include/GL",&lt;br /&gt;&lt;br /&gt;              EXT+"/include",&lt;br /&gt;              EXT+"/include/GL",&lt;br /&gt;              EXT+"/include/freetype2",&lt;br /&gt;   "modules/cealign/src",&lt;br /&gt;   "modules/cealign/src/tnt",&lt;br /&gt;              ]&lt;br /&gt;    libs=[]&lt;br /&gt;    pyogl_libs = []&lt;br /&gt;    lib_dirs=[]&lt;br /&gt;    def_macros=[("_PYMOL_MODULE",None),&lt;br /&gt;                ("_PYMOL_LIBPNG",None),&lt;br /&gt;                ("_PYMOL_FREETYPE",None),&lt;br /&gt;                ]&lt;br /&gt;    ext_comp_args=[]&lt;br /&gt;    ext_link_args=[&lt;br /&gt;               "-L/usr/X11R6/lib", "-lGL", "-lXxf86vm",&lt;br /&gt;               "-L"+EXT+"/lib", "-lpng", "-lglut", "-lfreetype",&lt;br /&gt;               # my additions&lt;br /&gt;               "-lGLEW"&lt;br /&gt;               ]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And now it builds.  &lt;br /&gt;&lt;br /&gt;But..  after doing &lt;code&gt;./pymol&lt;/code&gt; the GUI hangs.  I think it's Python (IDLE?), which I never use.  &lt;br /&gt;&lt;br /&gt;However, I can get pymol to run from the command line with no GUI:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; pymol -c&lt;br /&gt; PyMOL(TM) Molecular Graphics System, Version 1.3.&lt;br /&gt;..&lt;br /&gt; Command mode. No graphics front end.&lt;br /&gt; Detected 2 CPU cores.  Enabled multithreaded rendering.&lt;br /&gt; PyMOL: normal program termination.&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I ran a short script and made a figure, it looks fine.  &lt;br /&gt;&lt;br /&gt;So then, we get wise words from Ned Deily (&lt;a href="http://code.activestate.com/lists/pythonmac-sig/22758/"&gt;here&lt;/a&gt;), and see (&lt;a href="http://stackoverflow.com/questions/6781558/why-does-idle-keep-crashing-mac/6781900#6781900"&gt;here&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;- You should not rely on the Apple-suppled Pythons if you want to use IDLE.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I thought about putting Tcl/Tk 8.4 in a different place, etc.&lt;br /&gt;&lt;br /&gt;But finally I said (f*** it) and I reformatted my drive to add a new partition, and then used my USB flash drive with the Lion Installer (post &lt;a href="http://telliott99.blogspot.com/2011/07/os-x-lion.html"&gt;here&lt;/a&gt;), and then I installed MacPorts and did &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;$ sudo port install pymol&lt;br /&gt;---&gt;  Computing dependencies for pymol&lt;br /&gt;---&gt;  Dependencies to be installed: freetype bzip2 zlib glew libpng mesa makedepend pkgconfig glib2 autoconf help2man gettext expat libiconv gperf ncurses ncursesw p5-locale-gettext perl5 perl5.12 perl5 perl5 m4 automake libtool xorg-xproto py27-libxml2 libxml2 libxml2 python27 db46 gdbm openssl python_select readline sqlite3 python27 xorg-dri2proto xorg-glproto xorg-libXfixes xorg-fixesproto xorg-libX11 xorg-bigreqsproto xorg-inputproto xorg-kbproto xorg-libXau xorg-libXdmcp xorg-libxcb xorg-libpthread-stubs xorg-xcb-proto xorg-util-macros xorg-xcmiscproto xorg-xextproto xorg-xf86bigfontproto xorg-xtrans xorg-libXi xorg-libXext xorg-libXmu xorg-libXt xorg-libsm xorg-libice py26-numeric python26 py26-pmw py26-tkinter tk Xft2 fontconfig xrender xorg-renderproto tcl xorg-libXScrnSaver xorg-scrnsaverproto xdpyinfo xorg-libXinerama xorg-xineramaproto xorg-libXtst xorg-recordproto xorg-libXxf86vm xorg-xf86vidmodeproto xorg-libdmx xorg-dmxproto&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Incredible!  Everything but the kitchen sink.  Perhaps even more incredible, it worked.  An hour or two later, we finish with:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&lt;br /&gt;---&gt;  Attempting to fetch pymol-1.4_2.darwin_11.x86_64.tbz2 from http://packages.macports.org/pymol&lt;br /&gt;---&gt;  Fetching pymol&lt;br /&gt;---&gt;  Verifying checksum(s) for pymol&lt;br /&gt;---&gt;  Extracting pymol&lt;br /&gt;---&gt;  Applying patches to pymol&lt;br /&gt;---&gt;  Configuring pymol&lt;br /&gt;---&gt;  Building pymol&lt;br /&gt;---&gt;  Staging pymol into destroot&lt;br /&gt;---&gt;  Installing pymol @1.4_2&lt;br /&gt;---&gt;  Activating pymol @1.4_2&lt;br /&gt;---&gt;  Cleaning pymol&lt;br /&gt;$ &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I got 1LMB.pdb from the PDB, and I ran this script with &lt;code&gt;pymol script.pml&lt;/code&gt;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;load ~/Desktop/1LMB.PDB&lt;br /&gt;hide everything&lt;br /&gt;select D1, chain 1&lt;br /&gt;select D2, chain 2&lt;br /&gt;select R1, chain 3&lt;br /&gt;select R2, chain 4&lt;br /&gt;deselect all&lt;br /&gt;show sticks, D1&lt;br /&gt;show sticks, D2&lt;br /&gt;show cartoon, R1&lt;br /&gt;show cartoon, R2&lt;br /&gt;color red, R1&lt;br /&gt;zoom active, -10&lt;br /&gt;move x, 4&lt;br /&gt;bg_color white&lt;br /&gt;ray 1200,1200&lt;br /&gt;png ~/Desktop/x.png&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and I got what's at the top of the post.  Pretty cool!  More later on this topic.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1349284425694876291?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1349284425694876291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1349284425694876291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1349284425694876291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1349284425694876291'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/pymol-1.html' title='PyMOL (1)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-E7IYbSFHH1Q/Tj2tQ3kXdEI/AAAAAAAABsg/tJZR6UWDRlY/s72-c/Screen%2BShot%2B2011-08-06%2Bat%2B4.11.31%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-737036289737889456</id><published>2011-08-05T11:51:00.002-04:00</published><updated>2011-08-05T12:04:40.153-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ctypes'/><title type='text'>Exploring ctypes (5)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I was a little snarky about how the &lt;code&gt;types&lt;/code&gt; docs start with all Windows examples, but once you get to &lt;a href="http://docs.python.org/library/ctypes.html#fundamental-data-types"&gt;here&lt;/a&gt; they are really excellent.  So I won't say too much more about them except to reproduce a fun example:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; from ctypes import *&lt;br /&gt;&gt;&gt;&gt; class cell(Structure):&lt;br /&gt;...     pass&lt;br /&gt;... &lt;br /&gt;&gt;&gt;&gt; cell._fields_ = [('name', c_char_p),&lt;br /&gt;...                  ('next', POINTER(cell))]&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; c1 = cell()&lt;br /&gt;&gt;&gt;&gt; c1.name = 'foo'&lt;br /&gt;&gt;&gt;&gt; c2 = cell()&lt;br /&gt;&gt;&gt;&gt; c2.name = 'bar'&lt;br /&gt;&gt;&gt;&gt; c1.next = pointer(c2)&lt;br /&gt;&gt;&gt;&gt; c2.next = pointer(c1)&lt;br /&gt;&gt;&gt;&gt; p = c1&lt;br /&gt;&gt;&gt;&gt; for i in range(8):&lt;br /&gt;...     print p.name,&lt;br /&gt;...     p = p.next[0]&lt;br /&gt;... &lt;br /&gt;foo bar foo bar foo bar foo bar&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This linked list is a classic example of something that needs a "forward declaration" of the cell type in C.&lt;br /&gt;&lt;br /&gt;One other small point, from the docs:&lt;br /&gt;&lt;blockquote&gt;Either the LoadLibrary() method of the dll loaders should be used, or you should load the library by creating an instance of CDLL by calling the constructor:&lt;/blockquote&gt;&lt;br /&gt;We used the second method before.  To use the first with the example from the other day (&lt;a href="http://telliott99.blogspot.com/2011/08/exploring-ctypes-2.html"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; import ctypes&lt;br /&gt;&gt;&gt;&gt; libadd = ctypes.cdll.LoadLibrary('add1.so')&lt;br /&gt;&gt;&gt;&gt; libadd.f1(2)&lt;br /&gt;3&lt;br /&gt;&gt;&gt;&gt; libadd.f1(2,3)&lt;br /&gt;3&lt;br /&gt;&gt;&gt;&gt; libadd.f1()&lt;br /&gt;1858614497&lt;br /&gt;&gt;&gt;&gt; libadd.f1.argtypes = [ctypes.c_int]&lt;br /&gt;&gt;&gt;&gt; libadd.f1(2,3)&lt;br /&gt;3&lt;br /&gt;&gt;&gt;&gt; libadd.f1()&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "&lt;stdin&gt;", line 1, in &lt;module&gt;&lt;br /&gt;TypeError: this function takes at least 1 argument (0 given)&lt;br /&gt;&gt;&gt;&gt; &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;You can get some error checking with the &lt;code&gt;argtypes&lt;/code&gt; call, but not everything.&lt;br /&gt;&lt;br /&gt;A developer of &lt;a href="http://en.wikipedia.org/wiki/Cython"&gt;Cython&lt;/a&gt; gave a nice summary of why you might want to start with that in the SO &lt;a href="http://stackoverflow.com/questions/1942298/wrapping-a-c-library-in-python-c-cython-or-ctypes"&gt;post&lt;/a&gt; cited the other day.  But for my small purposes, I think &lt;code&gt;ctypes&lt;/code&gt; will probably be everything I'll need.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-737036289737889456?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/737036289737889456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=737036289737889456' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/737036289737889456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/737036289737889456'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/exploring-ctypes-5.html' title='Exploring ctypes (5)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-4663893160942537746</id><published>2011-08-05T08:08:00.002-04:00</published><updated>2011-08-05T08:23:33.451-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Note to self'/><title type='text'>Note to self:  .pth</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I think I finally got &lt;code&gt;.pth&lt;/code&gt; files sorted out.  I first ran into this with &lt;code&gt;easy_install&lt;/code&gt; (&lt;a href="http://telliott99.blogspot.com/2009/12/python-package-installations.html"&gt;here&lt;/a&gt;).  The Python library docs are &lt;a href="http://docs.python.org/library/site.html#module-site"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;span style="color:blue;"&gt;&lt;br /&gt;&lt;blockquote&gt;A path configuration file is a file whose name has the form package.pth and exists in one of the four directories mentioned above; its contents are additional items (one per line) to be added to sys.path. Non-existing items are never added to sys.path, but no check is made that the item refers to a directory (rather than a file). No item is added to sys.path more than once. Blank lines and lines beginning with # are skipped. Lines starting with import (followed by space or tab) are executed.&lt;br /&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;br /&gt;The four directories are:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sys.prefix + lib/site-packages&lt;br /&gt;sys.prefix + lib/site-python&lt;br /&gt;sys.exec_prefix + lib/site-packages&lt;br /&gt;sys.exec_prefix + lib/site-python&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So, not all directories on the path are searched for &lt;code&gt;.pth&lt;/code&gt; files.  I made a nested directory:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;/Users/telliott/Desktop/temp/x&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and put a &lt;code&gt;.pt&lt;/code&gt;h file in &lt;code&gt;site-packages&lt;/code&gt;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; cat /Library/Python/2.6/site-packages/x.pth&lt;br /&gt;/Users/telliott/Desktop/temp/x&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;To test it:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;gt; python -c 'import sys;  L = [p for p in sys.path if "Desk" in p];  print "\n".join(L)'&lt;br /&gt;/Users/telliott/Desktop/temp/x&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;Of course, I could have just added a path to &lt;code&gt;PYTHONPATH&lt;/code&gt; in &lt;code&gt;~/.bash_profile&lt;/code&gt;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;export PYTHONPATH=$PYTHONPATH:$HOME/Desktop/temp&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;gt; python -c 'import sys;  L = [p for p in sys.path if "Desk" in p];  print "\n".join(L)'&lt;br /&gt;/Users/telliott/Desktop/temp&lt;br /&gt;/Users/telliott/Desktop/temp/x&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;You need to restart Terminal to see the effect of changes to &lt;code&gt;PYTHONPATH&lt;/code&gt;.&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;It's worth emphasizing (as pointed out in the quote) that .pth files can contain code.  Here is &lt;code&gt;easy_install.pth&lt;/code&gt;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;gt; cat /Library/Python/2.6/site-packages/easy-install.pth&lt;br /&gt;import sys; sys.__plen = len(sys.path)&lt;br /&gt;./Sphinx-0.6.3-py2.6.egg&lt;br /&gt;./docutils-0.6-py2.6.egg&lt;br /&gt;./Jinja2-2.2.1-py2.6.egg&lt;br /&gt;./Pygments-1.1.1-py2.6.egg&lt;br /&gt;./rpy2-2.1.7_20101104-py2.6-macosx-10.6-universal.egg&lt;br /&gt;./numpy-1.5.0-py2.6-macosx-10.6-universal.egg&lt;br /&gt;./Cython-0.14-py2.6-macosx-10.6-universal.egg&lt;br /&gt;./PIL-1.1.7-py2.6-macosx-10.6-universal.egg&lt;br /&gt;import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;It seems roundabout, but &lt;code&gt;easy_install.pth&lt;/code&gt; is first adding these paths to &lt;code&gt;sys.path&lt;/code&gt;, and then moving them to the position in the path specified by &lt;code&gt;sys.__egginsert&lt;/code&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-4663893160942537746?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/4663893160942537746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=4663893160942537746' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4663893160942537746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4663893160942537746'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/note-to-self-pth.html' title='Note to self:  .pth'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-2454292775804124584</id><published>2011-08-04T19:27:00.004-04:00</published><updated>2011-08-04T19:43:15.126-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>SciPy on Lion (1)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I was looking for new things to do today, and realized I haven't really done much with SciPy.  Their page about installing it is &lt;a href="http://www.scipy.org/Installing_SciPy/Mac_OS_X"&gt;here&lt;/a&gt;.  It seems like the developers are tired of dealing with people who can't get it installed and recommend that you download a binary or at least, install the Python.org version of Python first.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Apple ships its own version of Python with OS X. However, we strongly recommend installing the official Python distribution.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Of course, I wasn't gonna do that.  There are other recommendations:  that you really ought to get readline (somehow better than what comes with OS X), that you should get and use gcc-4.0 (only gcc-4.2 on Lion that I could find), that you should set LDFLAGS and FFLAGS and so on.  I ignored it all.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; svn co http://svn.scipy.org/svn/scipy/trunk scipy&lt;br /&gt;&gt; cd scipy&lt;br /&gt;&gt; python setup.py build&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The build fails with &lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;unable to execute swig: No such file or directory&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; brew install swig&lt;br /&gt;Error: No available formula for swig&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;SWIG installation (download &lt;a href="http://www.swig.org/download.html"&gt;here&lt;/a&gt;) was a bit of a hiccup:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;configure: error: in `/Users/telliott/Desktop/swig-2.0.4':&lt;br /&gt;configure: error: &lt;br /&gt;        Cannot find pcre-config script from PCRE (Perl Compatible Regular Expressions)&lt;br /&gt;        library package. This dependency is needed for configure to complete,&lt;br /&gt;        Either:&lt;br /&gt;        - Install the PCRE developer package on your system (preferred approach).&lt;br /&gt;        - Download the PCRE source tarball, build and install on your system&lt;br /&gt;          as you would for any package built from source distribution.&lt;br /&gt;        - Use the Tools/pcre-build.sh script to build PCRE just for SWIG to statically&lt;br /&gt;          link against. Run 'Tools/pcre-build.sh --help' for instructions.&lt;br /&gt;          (quite easy and does not require privileges to install PCRE on your system)&lt;br /&gt;        - Use configure --without-pcre to disable regular expressions support in SWIG&lt;br /&gt;          (not recommended).&lt;br /&gt;&lt;br /&gt;./configure --without-pcre&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Back to SciPy and &lt;code&gt;python setup.py build&lt;/code&gt; and problems as described &lt;a href="http://projects.scipy.org/scipy/ticket/1476"&gt;here&lt;/a&gt;.  I'm not too swift with this svn/git stuff so rather than find the patched version I just patched the files:&lt;br /&gt;&lt;br /&gt;add &lt;code&gt;#include &amp;lt;complex.h&gt;&lt;/code&gt; to each of:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;scipy/linalg/src/fblaswrap_veclib_c.c&lt;br /&gt;scipy/lib/blas/fblaswrap_veclib_c.c.src&lt;br /&gt;scipy/sparse/linalg/eigen/arpack/ARPACK/FWRAPPERS/veclib_cabi_c.c&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And it seems to have built:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python&lt;br /&gt;Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) &lt;br /&gt;[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; from scipy import *&lt;br /&gt;&gt;&gt;&gt; &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I'll look into to testing it tomorrow.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-2454292775804124584?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/2454292775804124584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=2454292775804124584' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2454292775804124584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2454292775804124584'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/scipy-on-lion-1.html' title='SciPy on Lion (1)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3771937180552450134</id><published>2011-08-04T15:20:00.003-04:00</published><updated>2011-08-04T15:38:01.755-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ctypes'/><title type='text'>Exploring ctypes (4)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Introducing the subject of ctypes, I want to point you to a neat example from Andrew Dalke (second half of post &lt;a href="http://www.dalkescientific.com/writings/NBN/ctypes.html"&gt;here&lt;/a&gt;) that is a little beyond me, in many respects.  But I wanted to give a shout out, and also say that I got it to run with a minor tweak.&lt;br /&gt;&lt;br /&gt;• in the example file &lt;code&gt;integrators.c&lt;/code&gt;, it should read&lt;br /&gt;&lt;code&gt;double integrate_gq(probe_func_t f) {&lt;/code&gt;&lt;br /&gt;..&lt;br /&gt;&lt;code&gt;double integrate_rectangle(probe_func_t f) {&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;• the sym link for the built library should be (on 10.7):&lt;br /&gt;&lt;code&gt;ln -s build/lib.macosx-10.7-intel-2.7/integrators.so&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And here is the output I got running his examples by cut and paste.  First the build:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python setup.py build&lt;br /&gt;running build&lt;br /&gt;running build_ext&lt;br /&gt;building 'integrators' extension&lt;br /&gt;llvm-gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -fwrapv -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch x86_64 -pipe -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c integrators.c -o build/temp.macosx-10.7-intel-2.7/integrators.o&lt;br /&gt;creating build/lib.macosx-10.7-intel-2.7&lt;br /&gt;llvm-gcc-4.2 -Wl,-F. -bundle -undefined dynamic_lookup -Wl,-F. -arch i386 -arch x86_64 build/temp.macosx-10.7-intel-2.7/integrators.o -o build/lib.macosx-10.7-intel-2.7/integrators.so&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And the exploration in Python.  We load the library:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python&lt;br /&gt;Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) &lt;br /&gt;[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; import ctypes&lt;br /&gt;&gt;&gt;&gt; ctypes.CDLL("integrators.so")&lt;br /&gt;&amp;lth;CDLL 'integrators.so', handle 7fceb0483980 at 1056d9a90&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;We fail to get our C integrator function to accept the Python-defined "probe" function as argument:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; integrators = _&lt;br /&gt;&gt;&gt;&gt; integrators.integrate_rectangle&lt;br /&gt;&amp;lt;_FuncPtr object at 0x105759050&gt;&lt;br /&gt;&gt;&gt;&gt; def flat_probe(x):&lt;br /&gt;...     return 1.0&lt;br /&gt;... &lt;br /&gt;&gt;&gt;&gt; integrators.integrate_rectangle(flat_probe)&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "&amp;lt;stdin&gt;", line 1, in &amp;lt;module&gt;&lt;br /&gt;ctypes.ArgumentError: argument 1: &amp;lt;type 'exceptions.TypeError'&gt;: Don't know how to convert parameter 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;[ About _ in Python:  &lt;a href="http://stackoverflow.com/questions/4973185/r-equivalent-of-python"&gt;here&lt;/a&gt; and &lt;a href="http://docs.python.org/reference/lexical_analysis.html#reserved-classes-of-identifiers"&gt;here&lt;/a&gt; ]&lt;br /&gt;&lt;br /&gt;A simple cytypes.CFUNCTYPE definition does the trick:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; PROBE_FUNC = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)&lt;br /&gt;&gt;&gt;&gt; &lt;br /&gt;&gt;&gt;&gt; integrators.integrate_rectangle.argtypes = [PROBE_FUNC]&lt;br /&gt;&gt;&gt;&gt; integrators.integrate_rectangle.restype = ctypes.c_double&lt;br /&gt;&gt;&gt;&gt; integrators.integrate_rectangle(PROBE_FUNC(flat_probe)) &lt;br /&gt;2.0&lt;br /&gt;&gt;&gt;&gt; integrators.integrate_gq.argtypes=[PROBE_FUNC]&lt;br /&gt;&gt;&gt;&gt; integrators.integrate_gq.restype = ctypes.c_double&lt;br /&gt;&gt;&gt;&gt; integrators.integrate_gq(PROBE_FUNC(flat_probe))&lt;br /&gt;2.0&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And the original example&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; import math&lt;br /&gt;&gt;&gt;&gt; def probe_function(x):&lt;br /&gt;...     return math.cos(x)*(x+1)&lt;br /&gt;... &lt;br /&gt;&gt;&gt;&gt; integrators.integrate_gq(PROBE_FUNC(probe_function))&lt;br /&gt;1.6829416883812192&lt;br /&gt;&gt;&gt;&gt; integrators.integrate_rectangle(PROBE_FUNC(probe_function))&lt;br /&gt;1.7006012905844656&lt;br /&gt;&gt;&gt;&gt; &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Where I'm going:&lt;br /&gt;&lt;br /&gt;• ctypes library documentation&lt;br /&gt;• learn more about distutils&lt;br /&gt;&lt;br /&gt;Getting that build from these four lines is simply amazing:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;setup.py&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;from distutils.core import setup, Extension&lt;br /&gt;&lt;br /&gt;setup(name="integrators", version="0.0",&lt;br /&gt; ext_modules = [Extension("integrators", ["integrators.c"])])&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And for reference, in case the page ever goes away here are his code listings:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;integrators.h&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;#ifndef DALKE_INTEGRATORS_H&lt;br /&gt;#define DALKE_INTEGRATORS_H&lt;br /&gt;&lt;br /&gt;/* Two simple numerical integrators */&lt;br /&gt;&lt;br /&gt;typedef double (*probe_func_t)(double);&lt;br /&gt;&lt;br /&gt;double integrate_gq(probe_func_t f);&lt;br /&gt;double integrate_rectangle(probe_func_t f);&lt;br /&gt;&lt;br /&gt;#endif&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;integrators.c&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;/* Two numerical integrators */&lt;br /&gt;#include "integrators.h"&lt;br /&gt;&lt;br /&gt;/* 4 point Gaussian quadrature integration */&lt;br /&gt;double integrate_gq(probe_func_t f) {&lt;br /&gt; return &lt;br /&gt;  0.652145155*(f(+0.339981044) + f(-0.339981044)) +&lt;br /&gt;  0.347854845*(f(+0.861136312) + f(-0.861136312)); &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* 4 point rectangle rule */&lt;br /&gt;double integrate_rectangle(probe_func_t f) {&lt;br /&gt; return (f(-0.75)+f(-0.25)+f(0.25)+f(0.75))/2;&lt;br /&gt;}&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3771937180552450134?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3771937180552450134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3771937180552450134' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3771937180552450134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3771937180552450134'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/exploring-ctypes-4.html' title='Exploring ctypes (4)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3307914709397770142</id><published>2011-08-04T08:00:00.000-04:00</published><updated>2011-08-04T15:33:28.349-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ctypes'/><category scheme='http://www.blogger.com/atom/ns#' term='DNA binding sites'/><title type='text'>Exploring ctypes (3)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Continuing with ctypes---here is an example of scoring a genome for potential sites for a DNA-binding protein according to the methods we talked about &lt;a href="http://telliott99.blogspot.com/2010/12/dna-binding-sites-1.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We have a single function in a C module that will be compiled into a shared dynamic library.  Then we load that library from Python, using ctypes, and call the function.  The heavy lifting is done by the function &lt;code&gt;score&lt;/code&gt;.  The arguments are:&lt;br /&gt;&lt;br /&gt;• the DNA sequence as a string (a str on the Python side)&lt;br /&gt;• an array of floats which holds the scoring table&lt;br /&gt;  (in order acgt for each position in the site)&lt;br /&gt;• the length of the site (n = 2 in the example)&lt;br /&gt;• an array to hold the result for each position in the sequence&lt;br /&gt;&lt;br /&gt;other variables:&lt;br /&gt;&lt;br /&gt;• loop counters / index variables i, j, k&lt;br /&gt;• the current character, c, so we can print it&lt;br /&gt;• the current score for this char, d, also so we can print it&lt;br /&gt;• the current score for this position in the sequence, r&lt;br /&gt;&lt;br /&gt;The logic is straightforward and elementary.  (Although perhaps there are faster approaches that people might suggest?)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;mylib.c&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;#include &amp;lt;stdio.h&gt;&lt;br /&gt;#include &amp;lt;string.h&gt;&lt;br /&gt;&lt;br /&gt;void score(const char* dna, double p[], int n, double result[]) {&lt;br /&gt;    char c;&lt;br /&gt;    int i,j,k,N;&lt;br /&gt;    double d,r;&lt;br /&gt;    &lt;br /&gt;    N = strlen(dna)-n+1;&lt;br /&gt;    for (i=0; i&amp;lt;N; i++){&lt;br /&gt;        r = 0;&lt;br /&gt;        for (j=0; j&amp;lt;n; j++){&lt;br /&gt;            c = dna[i+j];&lt;br /&gt;            switch (c) {&lt;br /&gt;                case 'a': { k=0; break; }&lt;br /&gt;                case 'c': { k=1; break; }&lt;br /&gt;                case 'g': { k=2; break; }&lt;br /&gt;                case 't': { k=3; break; }&lt;br /&gt;            }&lt;br /&gt;            printf("%c ", c);&lt;br /&gt;            d = p[j*4 + k];&lt;br /&gt;            printf("%3.3f ",d);&lt;br /&gt;            r += d;&lt;br /&gt;        }&lt;br /&gt;        printf("%3.3f\n", r);&lt;br /&gt;        result[i] = r;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We build the shared library using clang (or gcc, a quick test showed no speed difference):&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;clang -g -Wall -c mylib.c&lt;br /&gt;clang -dynamiclib -current_version 1.0  mylib.o  -o mylib.dylib&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The Python script is a little more unusual.  The array initialization was just adapted from the docs (&lt;a href="http://docs.python.org/library/ctypes.html#arrays"&gt;here&lt;/a&gt;), I don't yet understand how it works.  (It seems like a pointer would be better). &lt;br /&gt;&lt;br /&gt;Here is the second of those:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;NFloats = ctypes.c_double * N&lt;br /&gt;result = [0.0] * N&lt;br /&gt;result = NFloats(*result)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And I was surprised that we don't have to worry about the types for arguments to our score function---that's why those lines are commented out at the top.&lt;br /&gt;&lt;br /&gt;For this toy example, the DNA sequence is 14 nt, and the scoring table is given in the list L. Here is the script:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;script.py&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;import ctypes&lt;br /&gt;pre = '/Users/telliott/Desktop'&lt;br /&gt;mylib = ctypes.CDLL(pre + '/mylib.dylib', ctypes.RTLD_GLOBAL)&lt;br /&gt;#mylib.score.argtypes = [ctypes.c_char_p]&lt;br /&gt;                        #ctypes.c_float_p,&lt;br /&gt;                        #ctypes.c_int]&lt;br /&gt;                        &lt;br /&gt;dna = 'actgtcgactcgag'&lt;br /&gt;L = [ 0.567,  -1.603,  -0.2245, 0.3605,&lt;br /&gt;     -0.1175, -0.4655, -0.5326, 0.6898 ]&lt;br /&gt;     &lt;br /&gt;EightFloats = ctypes.c_double * len(L)&lt;br /&gt;ff = EightFloats(*L)&lt;br /&gt;n = int(len(L)/4)&lt;br /&gt;N = len(dna) - n + 1&lt;br /&gt;&lt;br /&gt;NFloats = ctypes.c_double * N&lt;br /&gt;result = [0.0] * N&lt;br /&gt;result = NFloats(*result)&lt;br /&gt;&lt;br /&gt;mylib.score(dna, ff, n, result)&lt;br /&gt;for f in result[:6]:  print round(f,3)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Here's the output.  Each position is evaluated on a separate line.  The last six values printed are the results received back in Python.&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#b0ffff" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python script.py&lt;br /&gt;a 0.567 c -0.466 0.101&lt;br /&gt;c -1.603 t 0.690 -0.913&lt;br /&gt;t 0.360 g -0.533 -0.172&lt;br /&gt;g -0.225 t 0.690 0.465&lt;br /&gt;t 0.360 c -0.466 -0.105&lt;br /&gt;c -1.603 g -0.533 -2.136&lt;br /&gt;g -0.225 a -0.117 -0.342&lt;br /&gt;a 0.567 c -0.466 0.101&lt;br /&gt;c -1.603 t 0.690 -0.913&lt;br /&gt;t 0.360 c -0.466 -0.105&lt;br /&gt;c -1.603 g -0.533 -2.136&lt;br /&gt;g -0.225 a -0.117 -0.342&lt;br /&gt;a 0.567 g -0.533 0.034&lt;br /&gt;0.101&lt;br /&gt;-0.913&lt;br /&gt;-0.172&lt;br /&gt;0.465&lt;br /&gt;-0.105&lt;br /&gt;-2.136&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Not bad for 50 lines of code and a little more than an hour of work!  If you want to see it go fast, comment out the &lt;code&gt;printf&lt;/code&gt; statements in the C code, and change:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;dna = 'actgtcgactcgag'*400000&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now the DNA length is 5.6E6, and it finishes in about 5 seconds.  It's impressive.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3307914709397770142?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3307914709397770142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3307914709397770142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3307914709397770142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3307914709397770142'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/exploring-ctypes-3.html' title='Exploring ctypes (3)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7215593235926753566</id><published>2011-08-03T20:39:00.003-04:00</published><updated>2011-08-03T20:52:29.447-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ctypes'/><title type='text'>Exploring ctypes (2)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I used an example from before (&lt;a href="http://telliott99.blogspot.com/2011/01/os-x-library-basics-2.html"&gt;here&lt;/a&gt;) to make a dylib and then called the functions using ctypes.  It seems very easy:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;add1.c&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;int f1(int x) { return x + 1; }&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;add2.c&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;int f2(int x) { return x + 2; }&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; gcc -g -Wall -c add*.c&lt;br /&gt;&gt; gcc -dynamiclib -current_version 1.0  add*.o  -o libadd.dylib&lt;br /&gt;&gt; file libadd.dylib&lt;br /&gt;libadd.dylib: Mach-O 64-bit dynamically linked shared library x86_64&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python&lt;br /&gt;Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) &lt;br /&gt;[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; import ctypes&lt;br /&gt;&gt;&gt;&gt; pre = '/Users/telliott/Desktop'&lt;br /&gt;&gt;&gt;&gt; libadd = ctypes.CDLL(pre + '/libadd.dylib', ctypes.RTLD_GLOBAL)&lt;br /&gt;&gt;&gt;&gt; x = libadd.f1(1)&lt;br /&gt;&gt;&gt;&gt; x&lt;br /&gt;2&lt;br /&gt;&gt;&gt;&gt; y = libadd.f2(x)&lt;br /&gt;&gt;&gt;&gt; y&lt;br /&gt;4&lt;br /&gt;&gt;&gt;&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I guess one question is how to alter / determine the search path for ctypes in loading libraries.  &lt;code&gt;libc&lt;/code&gt; is in &lt;code&gt;/usr/lib&lt;/code&gt;, but &lt;code&gt;libpng&lt;/code&gt; is in &lt;code&gt;/usr/X11/lib&lt;/code&gt;, as we discussed the other day (&lt;a href="http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion-revised.html"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; libc = ctypes.CDLL('libc.dylib', ctypes.RTLD_GLOBAL)&lt;br /&gt;&gt;&gt;&gt; libpng = ctypes.CDLL('libpng.dylib', ctypes.RTLD_GLOBAL)&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "&lt;stdin&gt;", line 1, in &lt;module&gt;&lt;br /&gt;  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 353, in __init__&lt;br /&gt;    self._handle = _dlopen(self._name, mode)&lt;br /&gt;OSError: dlopen(libpng.dylib, 10): image not found&lt;br /&gt;&gt;&gt;&gt; pre = '/usr/X11/lib/'&lt;br /&gt;&gt;&gt;&gt; libpng = ctypes.CDLL(pre + 'libpng.dylib', ctypes.RTLD_GLOBAL)&lt;br /&gt;&gt;&gt;&gt; &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; import ctypes.util&lt;br /&gt;&gt;&gt;&gt; ctypes.util.find_library('libpng.dylib')&lt;br /&gt;&gt;&gt;&gt; ctypes.util.find_library('png')&lt;br /&gt;&gt;&gt;&gt; ctypes.util.find_library('AGL')&lt;br /&gt;'/System/Library/Frameworks/AGL.framework/AGL'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Obviously, find_library doesn't search &lt;code&gt;/usr/X11/lib&lt;/code&gt;.  Wonder if there is a way to tell it what we want?&lt;br /&gt;&lt;br /&gt;After we look at Andrew's more sophisticated &lt;a href="http://www.dalkescientific.com/writings/NBN/ctypes.html"&gt;examples&lt;/a&gt;, we'll try something relevant to bioinformatics&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7215593235926753566?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7215593235926753566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7215593235926753566' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7215593235926753566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7215593235926753566'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/exploring-ctypes-2.html' title='Exploring ctypes (2)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8379781878139689618</id><published>2011-08-03T08:30:00.002-04:00</published><updated>2011-08-03T20:39:41.747-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ctypes'/><title type='text'>Exploring ctypes (1)</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;A perennial question in Python is what to do when Python isn't fast enough, and a related one is how to work with C libraries from Python.  As discussed in this SO &lt;a href="http://stackoverflow.com/questions/1942298/wrapping-a-c-library-in-python-c-cython-or-ctypes"&gt;post&lt;/a&gt;, there are several possibilities, here I want to start working with &lt;a href="http://docs.python.org/library/ctypes.html"&gt;ctypes&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is now a Python built-in module.  I was a bit put off when I looked at the official docs, since all the early examples are windows and there is almost no mention of OS X. (However, I will have to make sure I understand what's there later), I'd start instead with Andrew Dalke's quick tutorial (&lt;a href="http://www.dalkescientific.com/writings/NBN/ctypes.html"&gt;here&lt;/a&gt;).  So the first part of this is my code duplicating a few of his examples.&lt;br /&gt;&lt;br /&gt;Getting started is literally one line, preceded by the import, and followed by the function call itself.  That's wonderful!&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; import ctypes&lt;br /&gt;&gt;&gt;&gt; libc = ctypes.CDLL("libc.dylib", ctypes.RTLD_GLOBAL)&lt;br /&gt;&gt;&gt;&gt; print libc.strlen("Hello world!")&lt;br /&gt;12&lt;br /&gt;&gt;&gt;&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It's pretty self-explanatory, if you're at all familiar with C, except for the constant &lt;code&gt;RTLD_GLOBAL&lt;/code&gt;.  Under the hood, the library &lt;code&gt;libc&lt;/code&gt; uses the functions &lt;code&gt;dlopen&lt;/code&gt; and friends defined in &lt;code&gt;clfcn.h&lt;/code&gt;.  (We touched on these once before, in the last example of this &lt;a href="http://telliott99.blogspot.com/2011/01/os-x-frameworks-bundles-2.html"&gt;post&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;The prototype for the C call to load a library is:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;void *dlopen(const char *file, int mode);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;RTLD_GLOBAL is one of several enumerated modes, and the value we provide is passed in as an argument to dlopen.  You can read about dlopen &lt;a href="http://pubs.opengroup.org/onlinepubs/7908799/xsh/dlopen.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here is &lt;code&gt;printf&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; libc.printf("the number %d and string %s\n", 10, 'spam')&lt;br /&gt;the number 10 and string spam&lt;br /&gt;30&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I'm not sure why this works, because in the standard C library, &lt;code&gt;printf&lt;/code&gt; is in &lt;code&gt;libstdio&lt;/code&gt; (&lt;a href="http://www.utas.edu.au/infosys/info/documentation/C/CStdLib.html#stdlib.h"&gt;ref&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;The function &lt;code&gt;printf&lt;/code&gt; returns the number of characters printed, or a negative value to indicate an error.  The next example introduces the idea that frequently we need to tell ctypes the type of input arguments or return values.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; libc.atoi('3')&lt;br /&gt;3&lt;br /&gt;&gt;&gt;&gt; libc.atof('3.14')&lt;br /&gt;3&lt;br /&gt;&gt;&gt;&gt; libc.atof.restype = ctypes.c_double&lt;br /&gt;&gt;&gt;&gt; libc.atof('3.14')&lt;br /&gt;3.14&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The assumed return type is int, and in order to get this example to work we have to specify that the returned value is a double.  Here's the prototype:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;double atof (const char *str);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Argument types are specified like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; libc.atan2.argtypes = [ctypes.c_double, ctypes.c_double]&lt;br /&gt;&gt;&gt;&gt; libc.atan2.restype = ctypes.c_double&lt;br /&gt;&gt;&gt;&gt; libc.atan2(3.0, 4.0)&lt;br /&gt;0.6435011087932844&lt;br /&gt;&gt;&gt;&gt; import math&lt;br /&gt;&gt;&gt;&gt; math.atan2(3.0, 4.0)&lt;br /&gt;0.6435011087932844&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Finally, here's another function, this one from the math library:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt;&gt;&gt; libmath = ctypes.CDLL("libm.dylib", ctypes.RTLD_GLOBAL)&lt;br /&gt;&gt;&gt;&gt; libmath.sqrt.restype = ctypes.c_double&lt;br /&gt;&gt;&gt;&gt; libmath.sqrt(2)&lt;br /&gt;nan&lt;br /&gt;&gt;&gt;&gt; libmath.sqrt(2.0)&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "&lt;stdin&gt;", line 1, in &lt;module&gt;&lt;br /&gt;ctypes.ArgumentError: argument 1: &lt;type 'exceptions.TypeError'&gt;: Don't know how to convert parameter 1&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&gt;&gt;&gt; libmath.sqrt.argtypes = [ctypes.c_double]&lt;br /&gt;&gt;&gt;&gt; libmath.sqrt(2)&lt;br /&gt;1.4142135623730951&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And here is a glowing &lt;a href="http://pysnippet.blogspot.com/2009/12/when-ctypes-comes-to-rescue.html"&gt;testimonial&lt;/a&gt; about controlling a camera via USB with code written in Python.&lt;br /&gt;&lt;br /&gt;It'd be interesting to see what we could do on that in OS X.  &lt;br /&gt;&lt;br /&gt;Still to do:&lt;br /&gt;&lt;br /&gt;• finish Andrew's tutorial (lots more there)&lt;br /&gt;• read the official docs&lt;br /&gt;• try to apply it to the problem of finding binding sites (&lt;a href="http://telliott99.blogspot.com/search/label/DNA%20binding%20sites"&gt;here&lt;/a&gt;)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8379781878139689618?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8379781878139689618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8379781878139689618' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8379781878139689618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8379781878139689618'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/exploring-ctypes-1.html' title='Exploring ctypes (1)'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-120900435385454697</id><published>2011-08-03T08:00:00.001-04:00</published><updated>2011-08-26T06:44:20.760-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><category scheme='http://www.blogger.com/atom/ns#' term='simulation'/><title type='text'>e again</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I came across a neat quote from Martin Gardner:&lt;br /&gt;&lt;font color="blue"&gt;&lt;br /&gt;&lt;blockquote&gt;The number &lt;i&gt;e&lt;/i&gt; is as ubiquitous as pi, turning up everywhere, and especially in probability theory.  If you randomly select real numbers between 0 and 1, and continue until their sum exceeds 1, the expected number of choices is &lt;i&gt;e&lt;/i&gt;.&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;-Martin Gardner &lt;br /&gt;   note in Calculus Made Easy, p. 153&lt;br /&gt;&lt;br /&gt;Of course, this begs for a Python simulation:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;import random&lt;br /&gt;&lt;br /&gt;def mean(L):&lt;br /&gt;    return float(sum(L))/len(L)&lt;br /&gt;&lt;br /&gt;def oneTrial():&lt;br /&gt;    counter = 1&lt;br /&gt;    f = random.random()&lt;br /&gt;    while f &lt;= 1:&lt;br /&gt;        counter +=1&lt;br /&gt;        f += random.random()&lt;br /&gt;    return counter&lt;br /&gt;&lt;br /&gt;N = int(1E7)&lt;br /&gt;L = [oneTrial() for i in range(N)]&lt;br /&gt;print mean(L)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#b0ffff" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python script.py &lt;br /&gt;2.7183671&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;A derivation would be nice, but that'll have to wait. I wonder about the variance.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-120900435385454697?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/120900435385454697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=120900435385454697' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/120900435385454697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/120900435385454697'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/e-again.html' title='e again'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-4969217903922077474</id><published>2011-08-03T05:18:00.005-04:00</published><updated>2011-08-03T09:21:25.614-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>pkg-config</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;A reasonably brief post about &lt;code&gt;pkg-config&lt;/code&gt;, which we used to help build matplotlib the other day (&lt;a href="http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion-revised.html"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;The web page is &lt;a href="http://www.freedesktop.org/wiki/Software/pkg-config"&gt;here&lt;/a&gt; and there is a guide &lt;a href="http://people.freedesktop.org/~dbn/pkg-config-guide.html"&gt;here&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;As it says on the first page:&lt;br /&gt;&lt;font color="blue"&gt;&lt;br /&gt;&lt;blockquote&gt;pkg-config is a helper tool used when compiling applications and libraries. It helps you insert the correct compiler options on the command line so an application can use  gcc -o test test.c `pkg-config --libs --cflags glib-2.0`  for instance, rather than hard-coding values on where to find glib (or other libraries). It is language-agnostic, so it can be used for defining the location of documentation tools, for instance.&lt;br /&gt;&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;And from the man page:&lt;br /&gt;&lt;br /&gt;&lt;font color="blue"&gt;&lt;br /&gt;&lt;blockquote&gt;DESCRIPTION&lt;br /&gt;       The pkg-config program  is  used  to  retrieve&lt;br /&gt;       information  about  installed libraries in the&lt;br /&gt;       system.  It is typically used to  compile  and&lt;br /&gt;       link against one or more libraries.  Here is a&lt;br /&gt;       typical usage scenario in a Makefile:&lt;br /&gt;&lt;br /&gt;       program: program.c&lt;br /&gt;            cc program.c $(pkg-config --cflags --libs gnomeui)&lt;br /&gt;&lt;br /&gt;       pkg-config retrieves information  about  pack-&lt;br /&gt;       ages  from special metadata files. These files&lt;br /&gt;       are named after the package,  and  has  a  .pc&lt;br /&gt;       extension.   On most systems, pkg-config looks&lt;br /&gt;       in and&lt;br /&gt;        for these files.  It will  additionally  look&lt;br /&gt;       in the colon-separated (on Windows, semicolon-&lt;br /&gt;       separated) list of  directories  specified  by&lt;br /&gt;       the PKG_CONFIG_PATH environment variable.&lt;br /&gt;&lt;br /&gt;       The  package  name specified on the pkg-config&lt;br /&gt;       command line is defined to be the name of  the&lt;br /&gt;       metadata  file,  minus the .pc extension. If a&lt;br /&gt;       library can install multiple versions simulta-&lt;br /&gt;       neously,  it  must  give  each version its own&lt;br /&gt;       name (for example,  GTK  1.2  might  have  the&lt;br /&gt;       package   name   "gtk+"   while  GTK  2.0  has&lt;br /&gt;       "gtk+-2.0").&lt;br /&gt;&lt;/blockquote&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;What's happening is that the matplotlib &lt;code&gt;setup.py&lt;/code&gt; script uses &lt;code&gt;pkg-config&lt;/code&gt; if it's present.  The binary is in &lt;code&gt;/usr/local/bin/pkg-config&lt;/code&gt;.  It looks for a subdirectory of &lt;code&gt;/usr/X11/lib&lt;/code&gt; (and &lt;code&gt;/usr/local/lib&lt;/code&gt;) called &lt;code&gt;pkgconfig&lt;/code&gt; that constains &lt;code&gt;.pc&lt;/code&gt; files for packages that specify metadata about themselves to take advantage of &lt;code&gt;pkgconfig&lt;/code&gt; functionality:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; cat /usr/X11/lib/pkgconfig/libpng.pc&lt;br /&gt;prefix=/usr/X11&lt;br /&gt;exec_prefix=${prefix}&lt;br /&gt;libdir=${exec_prefix}/lib&lt;br /&gt;includedir=${prefix}/include/libpng12&lt;br /&gt;&lt;br /&gt;Name: libpng&lt;br /&gt;Description: Loads and saves PNG files&lt;br /&gt;Version: 1.2.44&lt;br /&gt;Libs: -L${libdir} -lpng12&lt;br /&gt;Libs.private: -lz &lt;br /&gt;Cflags: -I${includedir} &lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;br /&gt;We used Homebrew only to grab &lt;code&gt;pkg-config&lt;/code&gt;.  You could get it yourself:  0.26 is the newest, but requires &lt;code&gt;glib-2.0&lt;/code&gt;;  0.25 bundles &lt;code&gt;glib&lt;/code&gt; with &lt;code&gt;pkg-config&lt;/code&gt;.  0.25 builds with no dependencies using the standard &lt;code&gt;./configure;  make;  make install&lt;/code&gt;.  Download page for version 0.25 and 0.26 is &lt;a href="http://pkgconfig.freedesktop.org/releases/"&gt;here&lt;/a&gt;.  Or of course, you can use &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt; like we &lt;a href="http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion-revised.html"&gt;did&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Not clear why it doesn't ship with OS X.  The license is GPLv2.  But then, so is &lt;a href="http://www.gnu.org/s/bash/"&gt;BASH&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Some minor issues:&lt;br /&gt;&lt;br /&gt;• when I tried using &lt;code&gt;pkg-config&lt;/code&gt; on my iMac (Snow Leopard, littered with MacPorts and other stuff), matplotlib seemed to build and install but died with:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python x.py&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "x.py", line 1, in &lt;module&gt;&lt;br /&gt;    import matplotlib.pyplot as plt&lt;br /&gt;  File "/Library/Python/2.6/site-packages/matplotlib/pyplot.py", line 95, in &lt;module&gt;&lt;br /&gt;    new_figure_manager, draw_if_interactive, _show = pylab_setup()&lt;br /&gt;  File "/Library/Python/2.6/site-packages/matplotlib/backends/__init__.py", line 25, in pylab_setup&lt;br /&gt;    globals(),locals(),[backend_name])&lt;br /&gt;  File "/Library/Python/2.6/site-packages/matplotlib/backends/backend_macosx.py", line 243, in &lt;module&gt;&lt;br /&gt;    class TimerMac(_macosx.Timer, TimerBase):&lt;br /&gt;AttributeError: 'module' object has no attribute 'Timer'&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;For reasons that I don't understand, the version of the file in the build directory&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;/Users/telliott/Software/matplotlib-1.0.1/build/lib.macosx-10.6-universal-2.6/matplotlib/backends/backend_macosx.py&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;is not the same as the one in &lt;code&gt;site-packages&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;/Library/Python/2.6/site-packages/matplotlib/backends/backend_macosx.py&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Simply replacing the &lt;code&gt;site-packages&lt;/code&gt; version fixed the problem:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; sudo cp /Users/telliott/Software/matplotlib-1.0.1/build/lib.macosx-10.6-universal-2.6/matplotlib/backends/backend_macosx.py /Library/Python/2.6/site-packages/matplotlib/backends/backend_macosx.py&lt;br /&gt;&gt; python -c "import matplotlib.pyplot as plt"&lt;br /&gt;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;• the Homebrew "Formula" in &lt;code&gt;/usr/local/Library/Formula/pkg-config.rb&lt;/code&gt; tells the installed &lt;code&gt;pkg-config&lt;/code&gt; which paths to search for &lt;code&gt;lib.pc&lt;/code&gt; files:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;        /usr/local/lib/pkgconfig&lt;br /&gt;        /usr/lib/pkgconfig&lt;br /&gt;        /usr/X11/lib/pkgconfig&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I'm not quite sure how that would work for a manual install.&lt;br /&gt;&lt;br /&gt;• the libpng in &lt;code&gt;/usr/local/lib&lt;/code&gt; that I installed shadowed the one in &lt;code&gt;/usr/X11/lib&lt;/code&gt; so to use the X11 version, I removed the files from &lt;code&gt;/usr/local&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;• The notation &lt;code&gt;libpng.pc&lt;code&gt;file&lt;/code&gt;Libs.private: -lz&lt;/code&gt; indicates that &lt;code&gt;libpng&lt;/code&gt; does depend on &lt;code&gt;zlib&lt;/code&gt;, but it's already been linked against it (hence private).  I'm not sure where it is, though.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-4969217903922077474?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/4969217903922077474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=4969217903922077474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4969217903922077474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/4969217903922077474'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/08/pkg-config.html' title='pkg-config'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7770051939640218772</id><published>2011-07-31T15:25:00.006-04:00</published><updated>2011-08-27T04:49:09.145-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='matplotlib'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>matplotlib on OS X Lion--revised</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;In the previous &lt;a href="http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion.html"&gt;post&lt;/a&gt;, I repeated an installation of matplotlib (now for OS X Lion) following the same method that I've linked to a number of times on the blog.  It worked this time as well, but lead me to consideration of other possible methods.  I found one on the web &lt;a href="http://the.taoofmac.com/space/blog/2011/07/24/2222"&gt;here&lt;/a&gt;.  So that's what this post is about.&lt;br /&gt;&lt;br /&gt;BTW, whatever you do, do not follow the instructions that the matplotlib developers provide.  You do not need another Python, including MacPython or the Endthought distribution or anything else..&lt;br /&gt;&lt;br /&gt;To recap, matplotlib lists dependencies (in the &lt;code&gt;make.osx&lt;/code&gt; file) of:  libpng, libfreetype, and zlib.  I read somewhere on the matplotlib site today (but can't find the link now) that zlib is not a required dependency.  These days, the other two are actually provided by Apple:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; ls -al /usr/X11/lib/libpng*&lt;br /&gt;-rwxr-xr-x  1 root  wheel  296864 Jul 29 16:11 /usr/X11/lib/libpng.3.dylib&lt;br /&gt;lrwxr-xr-x  1 root  wheel      14 Jul 29 16:11 /usr/X11/lib/libpng.dylib -&gt; libpng15.dylib&lt;br /&gt;-rwxr-xr-x  1 root  wheel  294160 Jul 29 16:11 /usr/X11/lib/libpng12.0.dylib&lt;br /&gt;-rwxr-xr-x  1 root  wheel  305008 Jul 29 16:11 /usr/X11/lib/libpng15.15.dylib&lt;br /&gt;lrwxr-xr-x  1 root  wheel      17 Jul 29 16:11 /usr/X11/lib/libpng15.dylib -&gt; libpng15.15.dylib&lt;br /&gt;&lt;br /&gt;&gt; ls -al /usr/X11/lib/libfreetype*&lt;br /&gt;-rwxr-xr-x  1 root  wheel  1060416 Jul 29 16:11 /usr/X11/lib/libfreetype.6.dylib&lt;br /&gt;lrwxr-xr-x  1 root  wheel       19 Jul 29 16:11 /usr/X11/lib/libfreetype.dylib -&gt; libfreetype.6.dylib&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I'm not sure at the moment whether X11 came with Xcode (as it used to) or was present in the original Lion install.&lt;br /&gt;&lt;br /&gt;In any case, I spent an hour or two trying to figure out how to use the build commands from the makefile that comes with matplotlib, but point at these libraries.  In the process I found what appears to be a bug:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;/usr/X11/include/png.h:666: error: forward declaration of ‘struct png_info_def’&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;(and see Prashant's answer &lt;a href="http://stackoverflow.com/questions/6800488/installing-matplotlib-in-mac-osx-lion/6809293#6809293"&gt;here&lt;/a&gt;), but we're going to use a different approach so it doesn't matter.  I'm not sure how our method solved this in the end.  As mentioned, the approach is to use &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt;, in particular, something called &lt;code&gt;pkgconfig&lt;/code&gt;.  I used a Ruby script that downloads and installs Homebrew, as described &lt;a href="https://github.com/mxcl/homebrew/wiki/installation"&gt;here&lt;/a&gt;.  The install gave this warning:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;Warning: The following *evil* dylibs exist in /usr/local/lib&lt;br /&gt;They may break builds or worse. You should consider deleting them:&lt;br /&gt;/usr/local/lib/libfreetype.6.dylib&lt;br /&gt;/usr/local/lib/libpng.3.dylib&lt;br /&gt;/usr/local/lib/libpng12.0.dylib&lt;br /&gt;/usr/local/lib/libz.1.2.5.dylib&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;These are, of course, the libraries we just installed in order to get matplotlib to build.&lt;br /&gt;&lt;br /&gt;That's what got me working on the other method more seriously.  I don't think the danger is all that great, but clearly it is better to use libraries that are (i) still available from the maintainers and (ii) have been vetted at least to some extent by other folks including Apple.  AFAIK there aren't any known security issues with the versions we installed previously.  I ripped them out anyway (they seemed to confuse &lt;code&gt;pkgconfig&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;If we ask Homebrew for the libraries, it just points us to the ones we saw in &lt;code&gt;/usr/X11&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; brew search libpng&lt;br /&gt;Apple distributes libpng with OS X, you can find it in /usr/X11/lib.&lt;br /&gt;However not all build scripts look here, so you may need to call ENV.x11&lt;br /&gt;in your formula's install function.&lt;br /&gt;&lt;br /&gt;&gt; brew search freetype&lt;br /&gt;Apple distributes freetype with OS X, you can find it in /usr/X11/lib.&lt;br /&gt;However not all build scripts look here, so you may need to call ENV.x11&lt;br /&gt;in your formula's install function.&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Following the instructions in the blog &lt;a href="http://the.taoofmac.com/space/blog/2011/07/24/2222"&gt;post&lt;/a&gt; I first installed &lt;code&gt;pkgconfig&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; sudo brew install pkgconfig&lt;br /&gt;Cowardly refusing to `sudo brew'&lt;br /&gt;&gt; brew install pkgconfig&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;!!&lt;br /&gt;&lt;br /&gt;That's all the Homebrew we need.  This is followed by:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;cd ~/Desktop&lt;br /&gt;git clone git://github.com/matplotlib/matplotlib.git&lt;br /&gt;cd matplotlib/&lt;br /&gt;python setup.py build&lt;br /&gt;sudo python setup.py install&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And we can see that I really did overwrite the first matplotlib install, and that we're actually using the libraries from /usr/X11, by first doing&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;export DYLD_PRINT_LIBRARIES=1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Then when we run a script that imports &lt;code&gt;matplotlib.pyplot&lt;/code&gt;, the Terminal shows (among much else) this:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;dyld: loaded: /usr/X11/lib/libfreetype.6.dylib&lt;br /&gt;..&lt;br /&gt;dyld: loaded: /usr/X11/lib/libpng15.15.dylib&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So that's what I'd recommend and it seems to be working fine.  This simple script works exactly as you'd expect.&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;import matplotlib.pyplot as plt&lt;br /&gt;Y = [1,4,9,16]&lt;br /&gt;plt.scatter(range(len(Y)),Y,s=250,color='r')&lt;br /&gt;plt.savefig('example.png')&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So the next thing to do is to figure out &lt;code&gt;pkgconfig&lt;/code&gt; and Homebrew work their magic!&lt;br /&gt;&lt;br /&gt;P.S. You will still need to make and edit &lt;code&gt;~/.matplotlib&lt;/code&gt;as discussed last time.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7770051939640218772?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7770051939640218772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7770051939640218772' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7770051939640218772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7770051939640218772'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion-revised.html' title='matplotlib on OS X Lion--revised'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1176362396280292144</id><published>2011-07-31T09:45:00.006-04:00</published><updated>2011-08-27T04:49:09.147-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OS X'/><category scheme='http://www.blogger.com/atom/ns#' term='matplotlib'/><category scheme='http://www.blogger.com/atom/ns#' term='software installs'/><title type='text'>matplotlib on OS X Lion--old</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;[ UPDATE:  I'm going to leave this post up, for the record, but I found a better way, and that's in the following &lt;a href="http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion-revised.html"&gt;post&lt;/a&gt;. ]&lt;br /&gt;&lt;br /&gt;Just a note to say that I got matplotlib installed with only a few issues to solve.  As before, I relied on Gavin Huttley's instructions (&lt;a href="http://bioinformatics.anu.edu.au/groups/huttleylab/wiki/da9fe/Building_matplotlib_for_Snow_Leopard.html"&gt;here&lt;/a&gt;).  Although the matplotlib instructions say you should install a different Python, I've found that just leads to confusion down the road, and I want to try to use the system version only if I can get away with it.  YMMV.&lt;br /&gt;&lt;br /&gt;The sticking points for the install always have to do with the basic dependencies, which are listed at the top of the file &lt;code&gt;make.osx&lt;/code&gt; in the matplotlib source (from &lt;a href="http://sourceforge.net/projects/matplotlib/files/matplotlib/matplotlib-1.0.1/"&gt;here&lt;/a&gt;).  The source is the last link at the bottom.&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&lt;br /&gt;ZLIBVERSION=1.2.3&lt;br /&gt;PNGVERSION=1.2.39&lt;br /&gt;FREETYPEVERSION=2.3.11&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;As silly as it seems, although OS X provides excellent functionality for dealing with compression, png images and fonts, we need to install these libraries for matplotlib to use.  Unfortunately, I'm not expert enough to alter matplotlib to get rid of these dependencies, so we're stuck with it.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;code&gt;&lt;b&gt;libpng&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I got libpng-1.2.39 from &lt;a href="http://sourceforge.net/projects/libpng/files/libpng12/older-releases/1.2.39/"&gt;here&lt;/a&gt;.  I used this version b/c that's what matplotlib asks for, despite the fact that the current release is 1.5.4 (&lt;a href="http://libpng.sourceforge.net/index.html"&gt;here&lt;/a&gt;).  Standard magic incantations:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;./configure&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;code&gt;&lt;b&gt;freetype&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;curl -O http://ftp.twaren.net/Unix/NonGNU/freetype/freetype-2.3.7.tar.bz2&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;According to Gavin's notes, we need these compiler flags for the other two (but they interfere with the libpng build):&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;export MACOSX_DEPLOYMENT_TARGET=10.7&lt;br /&gt;export CFLAGS="-arch i386 -arch x86_64"&lt;br /&gt;export FFLAGS="-arch i386 -arch x86_64"&lt;br /&gt;&lt;br /&gt;./configure&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;code&gt;&lt;b&gt;zlib&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;zlib is a compression library.  The current version is 1.2.5.  I tried this:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;curl -O http://www.zlib.net/zlib-1.2.3.tar.gz&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;but as I've seen before, although you get a (small) file back that has the right icon, it is really a &lt;code&gt;404 Page Not Found&lt;/code&gt;, which doesn't do me any good.  It seems the older versions have been disappeared off the web and I couldn't find them poking around on the site.  What I should've done at this point is try the version they do offer, but instead I went to my other machine and grabbed 1.2.3.  I guess that since I'd used it before to build zlib, I found I needed to &lt;code&gt;clean&lt;/code&gt; it first:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;make clean&lt;br /&gt;make&lt;br /&gt;sudo make install&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;code&gt;&lt;b&gt;matplotlib&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Finally, I got the matplotlib source.  I altered the file &lt;code&gt;make.osx&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;PREFIX=/usr/local&lt;br /&gt;PYVERSION=2.7&lt;br /&gt;PYTHON=python${PYVERSION}&lt;br /&gt;ZLIBVERSION=1.2.3&lt;br /&gt;PNGVERSION=1.2.39&lt;br /&gt;FREETYPEVERSION=2.3.7&lt;br /&gt;MACOSX_DEPLOYMENT_TARGET=10.7&lt;br /&gt;OSX_SDK_VER=10.7&lt;br /&gt;ARCH_FLAGS="-arch i386-arch x86_64"&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;make -f make.osx mpl_build&lt;br /&gt;sudo python setup.py install&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;mkdir ~/.matplotlib&lt;br /&gt;cp matplotlibrc.template ~/.matplotlib/matplotlibrc&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Edit the above file to have:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#b0ffff" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;backend      : MacOSX&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python&lt;br /&gt;Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) &lt;br /&gt;[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&gt;&gt;&gt; from matplotlib import *&lt;br /&gt;&gt;&gt;&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Yes!&lt;br /&gt;&lt;br /&gt;[ UPDATE:  I see I used freetype 2.3.7 rather than 2.3.11, by mistake. &lt;br /&gt;&lt;br /&gt;And if you don't like my approach, you could use &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt; and follow this &lt;a href="http://the.taoofmac.com/space/blog/2011/07/24/2222"&gt;post&lt;/a&gt;.  I don't have any experience with this yet.  ]&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1176362396280292144?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1176362396280292144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1176362396280292144' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1176362396280292144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1176362396280292144'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/07/matplotlib-on-os-x-lion.html' title='matplotlib on OS X Lion--old'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8212665635588813891</id><published>2011-07-30T10:42:00.006-04:00</published><updated>2011-07-31T10:34:36.132-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OS X'/><title type='text'>OS X Lion</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;OS X Lion has been released for a week now, so I thought I'd try it out on one of my machines.  A definitive review is &lt;a href="http://arstechnica.com/apple/reviews/2011/07/mac-os-x-10-7.ars"&gt;here&lt;/a&gt;.  I'll be too busy to really play with it for a while, or to do much programming, but I thought I should at least try.  An additional motivation is that my laptop (an aluminum MacBook from about December 08), had developed an issue.  It completely drains the battery (starting from full charge) in sleep mode, even when no apps are running.  The battery hasn't been particularly stressed:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  Health Information:&lt;br /&gt;  Cycle Count: 568&lt;br /&gt;  Condition: Normal&lt;br /&gt;  Battery Installed: Yes&lt;br /&gt;  Amperage (mA): 0&lt;br /&gt;  Voltage (mV): 12546&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And, it doesn't drain when powered off.  This problem appeared recently, and I am interested to see if installing Lion might fix it, but that hasn't been tested yet.  I'll update when I have those results.&lt;br /&gt;&lt;br /&gt;This post is just to document that I got Lion onto a USB flash drive and used it to do the install and it worked fine.  Instructions from &lt;a href="http://www.ithinkdiff.com/create-install-mac-os-lion-107-usb-external-drive-bootable/"&gt;here&lt;/a&gt;.  I did this because it's the only way to do a clean install.  One odd thing:  if the machine on which you are attempting to do the download can't run Lion, you won't be allowed to do the download at all!  I had to bring my laptop to work (and get the IT guys to reauthorize it for our network).  &lt;br /&gt;&lt;br /&gt;Also, I have two Apple IDs---an old one and one that goes with my MobileMe account.  When I set up Mail, the ID for the computer was automatically set to be the latter, but I originally did the Lion download with the former.  We'll see if and when that causes a problem.&lt;br /&gt;&lt;br /&gt;It seems clear that the Mac OS will (in time) become more iOS-like (locked down, user not allowed to risk hurting himself, even if he wants to) and less easy to hack around with.  But for now, it's still a win over Linux, for me.&lt;br /&gt;&lt;br /&gt;Python is 2.7:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&lt;br /&gt;&gt; python&lt;br /&gt;Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) &lt;br /&gt;[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin&lt;br /&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The default scrolling is like that on the iPhone---as if you're moving the content, rather than a scrollbar.  After 2 or 3 hours, I changed the setting back to the old method.  Maybe I will try to retrain my brain at a later date.&lt;br /&gt;&lt;br /&gt;I also downloaded Xcode 4.  It quit in the middle for no reason, but completed on the second try.  Weirdly, in the middle of the install I got this alert panel:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-7GHKTJCoDNU/TjQd8TPC_vI/AAAAAAAABsA/M63rfbPmAsI/s1600/Screen%2BShot%2B2011-07-30%2Bat%2B10.11.38%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 285px;" src="http://2.bp.blogspot.com/-7GHKTJCoDNU/TjQd8TPC_vI/AAAAAAAABsA/M63rfbPmAsI/s320/Screen%2BShot%2B2011-07-30%2Bat%2B10.11.38%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635161955540074226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I say "weirdly" because iTunes is not running.  Starting and quitting iTunes had no effect, either.  Finally I went in Terminal and looked for an iTunes-related process:&lt;br /&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;  163 ??         0:00.03 /Applications/iTunes.app/Contents/MacOS/iTunesHelper.app/Contents/MacOS/iTunesHelper -psn_0_57358&lt;br /&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;after I killed it, the install finished fine.  There is a mention in the big Ars Technica review that apps don't actually quit (or perhaps not always), and may not show the little dot for an active app, but there was no process for iTunes so I don't think so.  It's weird that a bug like that should still be present at this stage of the game.&lt;br /&gt;&lt;br /&gt;And I like the new looks in Terminal:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-YwcDmkjNGlE/TjQd8jy41NI/AAAAAAAABsI/okmxLF-E9eA/s1600/Screen%2BShot%2B2011-07-30%2Bat%2B11.05.36%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 67px;" src="http://1.bp.blogspot.com/-YwcDmkjNGlE/TjQd8jy41NI/AAAAAAAABsI/okmxLF-E9eA/s320/Screen%2BShot%2B2011-07-30%2Bat%2B11.05.36%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635161959985370322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[ UPDATE:  Yep, the battery does not drain on sleep anymore.  (Well, 2% in 2 hr).  That's the good news.  The bad news is that the extension I had to help autofill passwords when forms contain &lt;code&gt;autocomplete="off"&lt;/code&gt; doesn't work with Safari any more (post &lt;a href="http://telliott99.blogspot.com/2010/12/turn-autocompleteon.html"&gt;here&lt;/a&gt;, extension &lt;a href="http://lapcatsoftware.com/blog/2010/06/10/safari-extension-autocomplete/"&gt;here&lt;/a&gt;).  I sure hope Apple didn't do that on purpose. ]&lt;br /&gt;&lt;br /&gt;UPDATE 2:  I just needed to check to the right box in the Prefs.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-eUkUE24wecU/TjVnyb2Y1zI/AAAAAAAABsQ/MJ9zpmqgbUk/s1600/Screen%2BShot%2B2011-07-31%2Bat%2B10.33.02%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 86px;" src="http://1.bp.blogspot.com/-eUkUE24wecU/TjVnyb2Y1zI/AAAAAAAABsQ/MJ9zpmqgbUk/s320/Screen%2BShot%2B2011-07-31%2Bat%2B10.33.02%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635524624891041586" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8212665635588813891?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8212665635588813891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8212665635588813891' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8212665635588813891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8212665635588813891'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/07/os-x-lion.html' title='OS X Lion'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-7GHKTJCoDNU/TjQd8TPC_vI/AAAAAAAABsA/M63rfbPmAsI/s72-c/Screen%2BShot%2B2011-07-30%2Bat%2B10.11.38%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3780436008054835455</id><published>2011-07-15T07:34:00.003-04:00</published><updated>2011-07-15T07:46:07.334-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Verification</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;I posted two derivations for Euler's famous equation (&lt;a href="http://telliott99.blogspot.com/2011/07/eulers-gem.html"&gt;here&lt;/a&gt; and &lt;a href="http://telliott99.blogspot.com/2011/07/eulers-gem-2.html"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;e&lt;sup&gt;ix&lt;/sup&gt; = cos x + i sin x&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This can be verified in a particularly simple way.&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/Exponential_function"&gt;series&lt;/a&gt; representation of the exponential function:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;e&lt;sup&gt;x&lt;/sup&gt; =  1 +  x + x&lt;sup&gt;2&lt;/sup&gt;/2! +  x&lt;sup&gt;3&lt;/sup&gt;/3! + x&lt;sup&gt;4&lt;/sup&gt;/4! + ..&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;is especially neat because each term in the series is the derivative of the term following, and the result of that is:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;d/dx e&lt;sup&gt;x&lt;/sup&gt; = e&lt;sup&gt;x&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Which is, indeed, one definition of this function.  &lt;br /&gt;Substitution of &lt;code&gt;ix&lt;/code&gt; leads to a simple shift in the pattern:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;e&lt;sup&gt;ix&lt;/sup&gt; = 1 + ix - x&lt;sup&gt;2&lt;/sup&gt;/2! - ix&lt;sup&gt;3&lt;/sup&gt;/3! + x&lt;sup&gt;4&lt;/sup&gt;/4! + ..&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;repeating with a period of 4.  Powers of x like:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;4n + 1 are multiplied by  i&lt;br /&gt;4n + 2                   -1&lt;br /&gt;4n + 3                   -i&lt;br /&gt;4n                        1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;But remembering the &lt;a href="http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine.2C_and_tangent"&gt;series&lt;/a&gt; for sine and cosine, and multiplying the former by i:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;  sin x =  x -  x&lt;sup&gt;3&lt;/sup&gt;/3! + x&lt;sup&gt;5&lt;/sup&gt;/5! - x&lt;sup&gt;7&lt;/sup&gt;/7! + ..&lt;br /&gt;i sin x = ix - ix&lt;sup&gt;3&lt;/sup&gt;/3! + ..&lt;br /&gt;  cos x =  1 -  x&lt;sup&gt;2&lt;/sup&gt;/2! + x&lt;sup&gt;4&lt;/sup&gt;/4! - x&lt;sup&gt;6&lt;/sup&gt;/6! + ..&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Adding:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;cos x + i sin x = 1 + ix - x&lt;sup&gt;2&lt;/sup&gt;/2! - ix&lt;sup&gt;3&lt;/sup&gt;/3!+ x&lt;sup&gt;4&lt;/sup&gt;/4! + ..&lt;br /&gt;  = e&lt;sup&gt;ix&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3780436008054835455?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3780436008054835455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3780436008054835455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3780436008054835455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3780436008054835455'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/07/verification.html' title='Verification'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-1087881243793055730</id><published>2011-07-14T17:04:00.003-04:00</published><updated>2011-07-14T17:29:41.960-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Note on trig substitution</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;A fact we needed in a recent &lt;a href="http://telliott99.blogspot.com/2011/07/eulers-gem-2.html"&gt;post&lt;/a&gt; deriving Euler's formula is the value of a particular integral:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;int; dx / &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1) = ln (x + &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1))&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This gave me a lot more trouble than expected, so I thought I'd work through it here for reference.  The easiest way is to differentiate the answer.  Let:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;u = x + &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1)&lt;br /&gt;du = [1 + 2x / 2 &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1)] dx&lt;br /&gt;   = [1 + x / &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1)] dx&lt;br /&gt;&lt;br /&gt;y = ln(u)&lt;br /&gt;dy = 1/u du = [1 / (x + &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1)) ] [ 1 + x / (&amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1)] dx&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The trick is to notice that when we find the common denominator for the part at the far right and then add the terms, we generate the denominator of the part to the left.&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;dy = [1 / (x + &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1) ] [ (&amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1) + x) / (&amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1)] dx&lt;br /&gt;   = 1 / (&amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + 1)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The integrand is normally written more generally as:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;int; 1 / &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + a&lt;sup&gt;2&lt;/sup&gt;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and that doesn't change anything.&lt;br /&gt;&lt;br /&gt;The forward version starts with a trigonometric substitution.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-yoKf3onQTdw/Th9aSEa7w6I/AAAAAAAABr4/VPi9VDnVX5I/s1600/Screen%2Bshot%2B2011-07-14%2Bat%2B4.49.23%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 199px;" src="http://1.bp.blogspot.com/-yoKf3onQTdw/Th9aSEa7w6I/AAAAAAAABr4/VPi9VDnVX5I/s320/Screen%2Bshot%2B2011-07-14%2Bat%2B4.49.23%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5629317325707264930" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x = a tan y&lt;br /&gt;y = tan&lt;sup&gt;-1&lt;/sup&gt; (x/a)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://telliott99.blogspot.com/2010/04/another-fun-proof.html"&gt;Remembering&lt;/a&gt; that&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(u/v)' = (vu' - uv')/v&lt;sup&gt;2&lt;/sup&gt;&lt;br /&gt;tan' = (cos&lt;sup&gt;2&lt;/sup&gt; + sin&lt;sup&gt;2&lt;/sup&gt;)/cos&lt;sup&gt;2&lt;/sup&gt; = 1/cos&lt;sup&gt;2&lt;/sup&gt; = sec&lt;sup&gt;2&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;So&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;dx = a sec&lt;sup&gt;2&lt;/sup&gt; y dy&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The other part of the integral is:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;1 / &amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + a&lt;sup&gt;2&lt;/sup&gt;)&lt;br /&gt;&lt;br /&gt;x = a tan y&lt;br /&gt;x&lt;sup&gt;2&lt;/sup&gt; = a&lt;sup&gt;2&lt;/sup&gt; tan&lt;sup&gt;2&lt;/sup&gt; y&lt;br /&gt;x&lt;sup&gt;2&lt;/sup&gt; + a&lt;sup&gt;2&lt;/sup&gt; = a&lt;sup&gt;2&lt;/sup&gt; tan&lt;sup&gt;2&lt;/sup&gt; y + a&lt;sup&gt;2&lt;/sup&gt;&lt;br /&gt;  = a&lt;sup&gt;2&lt;/sup&gt; ( 1 + tan&lt;sup&gt;2&lt;/sup&gt; y)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;If we start with the standard identity:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sin&lt;sup&gt;2&lt;/sup&gt; y + cos&lt;sup&gt;2&lt;/sup&gt; y = 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and divide by &lt;code&gt;cos&lt;sup&gt;2&lt;/sup&gt; y&lt;/code&gt;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;tan&lt;sup&gt;2&lt;/sup&gt; y + 1 = sec&lt;sup&gt;2&lt;/sup&gt; y&lt;br /&gt;x&lt;sup&gt;2&lt;/sup&gt; = a&lt;sup&gt;2&lt;/sup&gt; ( 1 + tan&lt;sup&gt;2&lt;/sup&gt; y) = a&lt;sup&gt;2&lt;/sup&gt; sec&lt;sup&gt;2&lt;/sup&gt; y&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Thus the integral reduces to:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;int; (a sec&lt;sup&gt;2&lt;/sup&gt; y) / (a sec y)  dy = &amp;int; sec y dy&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This small integral is itself a bit tricky.  The answer, which I found on a really nice site (&lt;a href="http://math2.org/math/integrals/more/sec.htm"&gt;here&lt;/a&gt;), is to multiply top and bottom by:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;       sec y + tan y&lt;br /&gt;sec y  -------------&lt;br /&gt;       sec y + tan y&lt;br /&gt;&lt;br /&gt;Let u = sec y + tan y&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;If you work through it you'll see that&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;du = (sec y tan y + sec&lt;sup&gt;2&lt;/sup&gt; y) dy&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Thus, this is &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;int; du/u = ln(u) = ln (sec y + tan y) &lt;br /&gt;  = ln [ ((&amp;radic;(x&lt;sup&gt;2&lt;/sup&gt; + a&lt;sup&gt;2&lt;/sup&gt;) + x ) / a ]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;As I said, not so easy as other trig substitutions.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-1087881243793055730?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/1087881243793055730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=1087881243793055730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1087881243793055730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/1087881243793055730'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/07/note-on-trig-substitution.html' title='Note on trig substitution'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-yoKf3onQTdw/Th9aSEa7w6I/AAAAAAAABr4/VPi9VDnVX5I/s72-c/Screen%2Bshot%2B2011-07-14%2Bat%2B4.49.23%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-2971112735566975067</id><published>2011-07-14T09:30:00.005-04:00</published><updated>2011-07-15T07:08:02.084-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Euler's Gem 2</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Here is a sketch of a second derivation of Euler's famous formula:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;e&lt;sup&gt;i&amp;theta;&lt;/sup&gt; = cos&amp;theta; + i sin&amp;theta;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;as presented by William Dunham in his &lt;a href="http://www.amazon.com/Euler-Master-Dolciani-Mathematical-Expositions/dp/0883853280/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1310594415&amp;sr=1-1"&gt;book&lt;/a&gt; &lt;i&gt;Euler, The Master of Us All&lt;/i&gt;.  First post &lt;a href="http://telliott99.blogspot.com/2011/07/eulers-gem.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first step is to recall a standard trigonometric substitution in calculus:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-VOKNOtXxkQA/Th7zNfLujEI/AAAAAAAABrw/BW4FJrJoLVc/s1600/Screen%2Bshot%2B2011-07-14%2Bat%2B9.46.10%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 209px;" src="http://4.bp.blogspot.com/-VOKNOtXxkQA/Th7zNfLujEI/AAAAAAAABrw/BW4FJrJoLVc/s320/Screen%2Bshot%2B2011-07-14%2Bat%2B9.46.10%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5629203997294234690" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;y = sin x&lt;br /&gt;x = sin&lt;sup&gt;-1&lt;/sup&gt; y&lt;br /&gt;&lt;br /&gt;&amp;radic;(1 - y&lt;sup&gt;2&lt;/sup&gt;) = cos x&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We're interested in the integral:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;int; dy / &amp;radic;(1 - y&lt;sup&gt;2&lt;/sup&gt;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Substituting with x we see that:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;dy = cos x dx&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And the integral is&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;int; (1/cos x) cos x dx = &amp;int; dx = x&lt;br /&gt;x = &amp;int; dy / &amp;radic;(1 - y&lt;sup&gt;2&lt;/sup&gt;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Now Euler makes a complex change of variable:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;y = iz&lt;br /&gt;x = &amp;int; dy / &amp;radic;(1 - y&lt;sup&gt;2&lt;/sup&gt;)&lt;br /&gt;  = &amp;int; i dz / &amp;radic;(1-(iz)&lt;sup&gt;2&lt;/sup&gt;)&lt;br /&gt;  = i &amp;int; dz / &amp;radic;(1 + z&lt;sup&gt;2&lt;/sup&gt;)&lt;br /&gt;  = i ln [&amp;radic;(1 + z&lt;sup&gt;2&lt;/sup&gt;) + z]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The last step is another standard result from calculus which I will assume for the time being (more &lt;a href="http://telliott99.blogspot.com/2011/07/note-on-trig-substitution.html"&gt;here&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Undo the substitution:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;z = y/i = sin x / i&lt;br /&gt;z&lt;sup&gt;2&lt;/sup&gt; = -sin&lt;sup&gt;2&lt;/sup&gt; x&lt;br /&gt;&amp;radic;(1 + z&lt;sup&gt;2&lt;/sup&gt;) = &amp;radic;(1 - sin&lt;sup&gt;2&lt;/sup&gt; x)&lt;br /&gt;  = cos x&lt;br /&gt;&lt;br /&gt;x = i ln (cos x + sin x / i)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We will use two identities involving i:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;u / i = - i u&lt;br /&gt;1 / (cos u - i sin u) = (cos u + i sin u)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;(For the second one, see the previous &lt;a href="http://telliott99.blogspot.com/2011/07/eulers-gem.html"&gt;post&lt;/a&gt;).  Now:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x = i ln (cos x + sin x / i)&lt;br /&gt;x = i ln (cos x - i sin x)&lt;br /&gt;ix = - ln (cos x - i sin x)&lt;br /&gt;  = ln [ 1 / (cos x - i sin x) ]&lt;br /&gt;  = ln (cos x + i sin x)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Just eponentiate:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;e&lt;sup&gt;ix&lt;/sup&gt; = cos x + i sin x&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Wow, again!&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-2971112735566975067?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/2971112735566975067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=2971112735566975067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2971112735566975067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/2971112735566975067'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/07/eulers-gem-2.html' title='Euler&apos;s Gem 2'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-VOKNOtXxkQA/Th7zNfLujEI/AAAAAAAABrw/BW4FJrJoLVc/s72-c/Screen%2Bshot%2B2011-07-14%2Bat%2B9.46.10%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8856539240415099717</id><published>2011-07-13T17:42:00.004-04:00</published><updated>2011-07-13T18:02:39.349-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Euler's gem</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Here is a sketch of the derivation of Euler's famous formula:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;e&lt;sup&gt;i&amp;theta;&lt;/sup&gt; = cos&amp;theta; + i sin&amp;theta;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;as presented by William Dunham in his &lt;a href="http://www.amazon.com/Euler-Master-Dolciani-Mathematical-Expositions/dp/0883853280/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1310594415&amp;sr=1-1"&gt;book&lt;/a&gt; &lt;i&gt;Euler, The Master of Us All&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;The first part of the proof is similar to when we used Euler's formula to derive other formulas for trig functions of sums and differences of angles (&lt;a href="http://telliott99.blogspot.com/2011/05/note-about-sum-of-cosines-formula.html"&gt;post&lt;/a&gt;), only backward.  Start from the definition of i:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;i = &amp;radic;-1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;To begin with, having i allows us to factor new expressions:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;1 = cos&lt;sup&gt;2&lt;/sup&gt; s + sin&lt;sup&gt;2&lt;/sup&gt; s&lt;br /&gt;  = (cos s + i sin s)(cos s - i sin s)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;(I'm going to use s and t, as before, rather than &amp;theta; and &amp;phi;).  &lt;br /&gt;&lt;br /&gt;This shows where the original idea of cos + i sin comes from.  (Of course, we could just as well do sin + i cos, that would result in a different convention for the orientation of the &lt;a href="http://en.wikipedia.org/wiki/Complex_plane"&gt;complex plane&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Suppose we have two angles s and t, we can multiply and then use the formulas from before (obtained by the geometric proof):&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(cos s + i sin s)(cos t + i sin t) =&lt;br /&gt;  = (cos s cos t - sin s sin t) + i(sin s cos t + cos s sin t)&lt;br /&gt;  = cos(s + t) + i sin(s + t)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Set s = t:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(cos s + i sin s)&lt;sup&gt;2&lt;/sup&gt; = cos(2s) + i sin(2s)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;In fact Euler showed it works for fractional n but I'll assume that part:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;[1] (cos s + i sin s)&lt;sup&gt;n&lt;/sup&gt; = cos(ns) + i sin(ns)&lt;br /&gt;n &gt;= 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;If we multiply the difference rather than the sum:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(cos s - i sin s)(cos t - i sin t) =&lt;br /&gt;  = (cos s cos t - sin s sin t) - i (sin s cos t + cos s sin t)&lt;br /&gt;  = cos(s + t) - i sin(s + t)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Again, with s = t we have:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(cos s - i sin s)&lt;sup&gt;2&lt;/sup&gt; = cos(2s) - i sin(2s)&lt;br /&gt;[2] (cos s - i sin s)&lt;sup&gt;n&lt;/sup&gt; = cos(ns) - i sin(ns)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Adding [1] and [2] we have:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;2 cos(ns) = (cos s + i sin s)&lt;sup&gt;n&lt;/sup&gt; + (cos s - i sin s)&lt;sup&gt;n&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;The middle part of the proof is where the magic happens.  Let:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;s = x/n&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;As &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;n -&gt; &amp;infin;&lt;br /&gt;s -&gt; 0&lt;br /&gt;cos s -&gt; 1&lt;br /&gt;sin s -&gt; s&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;So..&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;cos x = cos ns = 1/2 [(cos s + i sin s)&lt;sup&gt;n&lt;/sup&gt; + (cos s - i sin s)&lt;sup&gt;n&lt;/sup&gt;]&lt;br /&gt;cos x = 1/2 [(1 + is)&lt;sup&gt;n&lt;/sup&gt; + (1 - is)&lt;sup&gt;n&lt;/sup&gt;]&lt;br /&gt;cos x = 1/2 [(1 + ix/n)&lt;sup&gt;n&lt;/sup&gt; + (1 - ix/n)&lt;sup&gt;n&lt;/sup&gt;]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;But..&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;e&lt;sup&gt;ix&lt;/sup&gt; = (1 + ix/n)&lt;sup&gt;n&lt;/sup&gt; &lt;br /&gt;as n -&gt; &amp;infin;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;So&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;cos x = 1/2 [e&lt;sup&gt;ix&lt;/sup&gt; + e&lt;sup&gt;-ix&lt;/sup&gt;]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;By very similar manipulation to what's in the first part we can also handle the sine:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;2i sin(ns) = (cos s + i sin s)&lt;sup&gt;n&lt;/sup&gt; - (cos s - i sin s)&lt;sup&gt;n&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We will obtain:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sin x = 1/(2i) [e&lt;sup&gt;ix&lt;/sup&gt; - e&lt;sup&gt;-ix&lt;/sup&gt;]&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Now it's just a matter of addition:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;cos x + i sin x = 1/2 [e&lt;sup&gt;ix&lt;/sup&gt; + e&lt;sup&gt;-ix&lt;/sup&gt; + e&lt;sup&gt;ix&lt;/sup&gt; - e&lt;sup&gt;-ix&lt;/sup&gt;]&lt;br /&gt;  = 1/2 [e&lt;sup&gt;ix&lt;/sup&gt; + e&lt;sup&gt;ix&lt;/sup&gt;]&lt;br /&gt;  = e&lt;sup&gt;ix&lt;/sup&gt;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Wow!&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8856539240415099717?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8856539240415099717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8856539240415099717' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8856539240415099717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8856539240415099717'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/07/eulers-gem.html' title='Euler&apos;s gem'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-8744904313780683832</id><published>2011-06-27T07:00:00.002-04:00</published><updated>2011-06-27T12:30:34.950-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Rotating a hyperbola:  general case</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Just to finish up quickly with the analysis of hyperbolas from the other day (&lt;a href="http://telliott99.blogspot.com/2011/06/different-views-same-parabola.html"&gt;here&lt;/a&gt; and &lt;a href="http://telliott99.blogspot.com/2011/06/rotational-transformation-geometrical.html"&gt;here&lt;/a&gt;), following Stewart (&lt;a href="http://www.stewartcalculus.com/data/CALCULUS%20Early%20Transcendentals/upfiles/RotationofAxes.pdf"&gt;pdf&lt;/a&gt;), we derived the following equations for x and y in terms of a coordinate system based on u and v (orthogonal, rotated through angle &amp;theta;):&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x = u cos&amp;theta; - v sin&amp;theta;&lt;br /&gt;y = u sin&amp;theta; + v cos&amp;theta;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The general formula for a quadratic is:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;Ax&lt;sup&gt;2&lt;/sup&gt; + Bxy + Cy&lt;sup&gt;2&lt;/sup&gt; + Dx + Ey + F = 0&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;When we transform to the new coordinates, we get:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;Ax&lt;sup&gt;2&lt;/sup&gt; = A[u&lt;sup&gt;2&lt;/sup&gt; cos&lt;sup&gt;2&lt;/sup&gt;&amp;theta; - 2uv sin&amp;theta; cos&amp;theta; + v&lt;sup&gt;2&lt;/sup&gt; sin&lt;sup&gt;2&lt;/sup&gt;&amp;theta;]&lt;br /&gt;Bxy = B[u&lt;sup&gt;2&lt;/sup&gt; cos&amp;theta; sin&amp;theta; + uv cos&lt;sup&gt;2&lt;/sup&gt;&amp;theta; - uv sin&lt;sup&gt;2&lt;/sup&gt;&amp;theta; - v&lt;sup&gt;2&lt;/sup&gt; sin&amp;theta; cos&amp;theta;&lt;br /&gt;Cy&lt;sup&gt;2&lt;/sup&gt; = C[u&lt;sup&gt;2&lt;/sup&gt; sin&lt;sup&gt;2&lt;/sup&gt;&amp;theta; + 2uv sin&amp;theta; cos&amp;theta; + v&lt;sup&gt;2&lt;/sup&gt; cos&lt;sup&gt;2&lt;/sup&gt;&amp;theta;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Gathering the terms in uv we obtain the coefficients:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(C-A)(2sin&amp;theta; cos&amp;theta;) + B(cos&lt;sup&gt;2&lt;/sup&gt;&amp;theta; - sin&lt;sup&gt;2&lt;/sup&gt;&amp;theta;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Remember the double angle formulas:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sin(s+t) = sin s cos t + cos s sin t&lt;br /&gt;sin(2&amp;theta;) = 2 sin&amp;theta; cos&amp;theta;&lt;br /&gt;&lt;br /&gt;cos(s+t = cos s cos t - sin s sin t&lt;br /&gt;cos(2&amp;theta;) = cos&lt;sup&gt;2&lt;/sup&gt;&amp;theta; - sin&lt;sup&gt;2&lt;/sup&gt;&amp;theta;&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;So we obtain:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(C-A) sin(2&amp;theta;) + B cos(2&amp;theta;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;for the coefficients of xy.  These must equal zero for all the xy terms to disappear.  Thus:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;tan(2&amp;theta;) = B / (C-A)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This approach runs into a problem if C = A, as it does for our example:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;xy = 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;But we can just invert the step at the end:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;cot(2&amp;theta;) = (C-A)/B = 0&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The cotangent is zero when the cosine is zero, e.g. for &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;2&amp;theta; = &amp;pi;/2&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Thus, if&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&amp;theta; = &amp;pi;/4&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;then all the xy terms vanish, as we found before.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-8744904313780683832?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/8744904313780683832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=8744904313780683832' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8744904313780683832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/8744904313780683832'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/06/just-to-finish-up-quickly-with-analysis.html' title='Rotating a hyperbola:  general case'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-3945755173391049332</id><published>2011-06-26T13:34:00.006-04:00</published><updated>2011-07-04T08:06:14.267-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Rotational transformation:  geometrical view</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-PicvyjL23SA/TgdvQStmr2I/AAAAAAAABrQ/1EB9_pwdXrM/s1600/Screen%2Bshot%2B2011-06-26%2Bat%2B1.41.00%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 314px;" src="http://1.bp.blogspot.com/-PicvyjL23SA/TgdvQStmr2I/AAAAAAAABrQ/1EB9_pwdXrM/s320/Screen%2Bshot%2B2011-06-26%2Bat%2B1.41.00%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5622584985487060834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;A bit more about rotational transformations (see the previous post for the setup to this).  We derived equations describing the coordinates of a point at x,y with respect to a new coordinate system in u,v that is rotated counter-clockwise by an angle &amp;theta;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x = u cos(&amp;theta;) - v sin(&amp;theta;)&lt;br /&gt;y = u sin(&amp;theta;) + v cos(&amp;theta;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We can also solve these equations for u and v.  (It helps to know the answer).  Notice that if we multiply the first equation by cos(&amp;theta;) and the second one by sin(&amp;theta;) and add, we'll end up with u by itself on the right-hand side:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x cos(&amp;theta;) = u cos&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;) - v sin(&amp;theta;) cos(&amp;theta;)&lt;br /&gt;y sin(&amp;theta;) = u sin&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;) + v cos(&amp;theta;) sin(&amp;theta;)&lt;br /&gt;&lt;br /&gt;x cos(&amp;theta;) + y sin(&amp;theta;) = u cos&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;) + u sin&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;) &lt;br /&gt;x cos(&amp;theta;) + y sin(&amp;theta;) = u&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Similarly, if we multiply the first equation by sin(&amp;theta;) and the second one by cos(&amp;theta;) and subtract the first from the second, we end up with v by itself:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x sin(&amp;theta;) = u sin(&amp;theta;) cos(&amp;theta;) - v sin&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;)&lt;br /&gt;y cos(&amp;theta;) = u sin(&amp;theta;) cos(&amp;theta;) + v cos&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;)&lt;br /&gt;&lt;br /&gt;- x sin(&amp;theta;) + y cos(&amp;theta) = v cos&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;) + v sin&lt;sup&gt;2&lt;/sup&gt;(&amp;theta;)&lt;br /&gt;- x sin(&amp;theta;) + y cos(&amp;theta) = v&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;I came up with geometric explanations for these relationships, the one for x and y in terms of u and v is at the top of the post, and below is the same drawing but explaining u and v in terms of x and y.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-G-KLeae_EYU/TgdtpzntqvI/AAAAAAAABrI/Rv8Iea9zFVQ/s1600/Screen%2Bshot%2B2011-06-26%2Bat%2B1.33.51%2BPM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 317px;" src="http://2.bp.blogspot.com/-G-KLeae_EYU/TgdtpzntqvI/AAAAAAAABrI/Rv8Iea9zFVQ/s320/Screen%2Bshot%2B2011-06-26%2Bat%2B1.33.51%2BPM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5622583224794196722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A quicker way to the same place is to start by considering u and v to be the original coordinate system, and rotate clockwise through the angle &amp;theta;.  Then &amp;theta; is negative, sin(&amp;theta;) = -sin(-&amp;theta;) and the cosine stays the same.  We end up switching the signs of the sine terms, as we found.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-3945755173391049332?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/3945755173391049332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=3945755173391049332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3945755173391049332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/3945755173391049332'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/06/rotational-transformation-geometrical.html' title='Rotational transformation:  geometrical view'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-PicvyjL23SA/TgdvQStmr2I/AAAAAAAABrQ/1EB9_pwdXrM/s72-c/Screen%2Bshot%2B2011-06-26%2Bat%2B1.41.00%2BPM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-189122277697401453</id><published>2011-06-26T10:56:00.009-04:00</published><updated>2011-06-26T13:35:17.024-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Different views, same hyperbola</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;In the algebra study guide that my son is using (&lt;a href="http://www.aleks.com/"&gt;ALEKS&lt;/a&gt;) they set up a hyperbola in two "standard" forms as:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(x-h)&lt;sup&gt;2&lt;/sup&gt;/a&lt;sup&gt;2&lt;/sup&gt; - (y-k)&lt;sup&gt;2&lt;/sup&gt;/b&lt;sup&gt;2&lt;/sup&gt; = 1&lt;br /&gt;(y-k)&lt;sup&gt;2&lt;/sup&gt;/b&lt;sup&gt;2&lt;/sup&gt; - (x-h)&lt;sup&gt;2&lt;/sup&gt;/a&lt;sup&gt;2&lt;/sup&gt; = 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;or more generally:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;(x-h)&lt;sup&gt;2&lt;/sup&gt;/a&lt;sup&gt;2&lt;/sup&gt; - (y-k)&lt;sup&gt;2&lt;/sup&gt;/b&lt;sup&gt;2&lt;/sup&gt; = +/- 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Let's simplify our lives and consider an example centered at the origin:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x&lt;sup&gt;2&lt;/sup&gt;/a&lt;sup&gt;2&lt;/sup&gt; - y&lt;sup&gt;2&lt;/sup&gt;/b&lt;sup&gt;2&lt;/sup&gt; = 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Then they divide the world into those hyperbolas that open up and down versus those that open up left and right.&lt;br /&gt;&lt;br /&gt;By looking at the equation, I think we can agree that if x&lt;sup&gt;2&lt;/sup&gt; equals 0 we've got a problem, since no value of y can satisfy the equation, and in fact x must not be less than 1.  Hence, we can already predict that this system opens left and right, as the plot shows (&lt;code&gt;a&lt;sup&gt;2&lt;/sup&gt; = b&lt;sup&gt;2&lt;/sup&gt; = 2&lt;/code&gt;):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-OLbJUi9wrUU/TgdPaXPLlgI/AAAAAAAABqw/EqukeKSwhDg/s1600/Screen%2Bshot%2B2011-06-26%2Bat%2B11.24.38%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 284px;" src="http://2.bp.blogspot.com/-OLbJUi9wrUU/TgdPaXPLlgI/AAAAAAAABqw/EqukeKSwhDg/s320/Screen%2Bshot%2B2011-06-26%2Bat%2B11.24.38%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5622549974128236034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The ALEKS review goes on to explain that for this type of equation, the vertices of the hyperbola (points of closest approach to the origin at &lt;code&gt;h,k&lt;/code&gt;) are equal to &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;h +/- a, k&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;and the asymptotes have slopes equal to&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;+/- b/a&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;This all works great.  The problem I had was that the simplest parabola I can think of is:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;xy = 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;which doesn't fit the system.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-uFyaOJlk0Ns/TgdPyOLkyOI/AAAAAAAABq4/yG1fnek4pYo/s1600/Screen%2Bshot%2B2011-06-26%2Bat%2B11.26.37%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 320px;" src="http://2.bp.blogspot.com/-uFyaOJlk0Ns/TgdPyOLkyOI/AAAAAAAABq4/yG1fnek4pYo/s320/Screen%2Bshot%2B2011-06-26%2Bat%2B11.26.37%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5622550384014051554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The answer to my confusion is that any parabola may be rotated around its origin in the xy-plane.  In 2 selected orientations its equation will have only &lt;code&gt;x&lt;sup&gt;2&lt;/sup&gt;&lt;/code&gt; and &lt;code&gt;y&lt;sup&gt;2&lt;/sup&gt;&lt;/code&gt; terms (when the vertices are on the x or the y-axis), whereas in 2 other selected orientations it may have only &lt;code&gt;xy&lt;/code&gt; terms (when the vertices are on &lt;code&gt;y= +/- x&lt;/code&gt;.  The rest of the time it contains both.&lt;br /&gt;&lt;br /&gt;This is explained in an excerpt from &lt;a href="http://www.stewartcalculus.com/"&gt;Stewart's Calculus&lt;/a&gt; I found &lt;a href="http://www.stewartcalculus.com/data/CALCULUS%20Early%20Transcendentals/upfiles/RotationofAxes.pdf"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Consider a point &lt;code&gt;P&lt;/code&gt; in the plane with coordinates &lt;code&gt;x,y&lt;/code&gt; and distance from the origin &lt;code&gt;r&lt;/code&gt;.  Now, let's establish a new coordinate system &lt;code&gt;u,v&lt;/code&gt; which is rotated counter-clockwise by the angle &lt;code&gt;&amp;theta;&lt;/code&gt;.  A vector from the origin through &lt;code&gt;P&lt;/code&gt; is rotated an angle &lt;code&gt;&amp;phi;&lt;/code&gt; with respect to the u axis and &lt;code&gt;&amp;phi; + &amp;theta;&lt;/code&gt; with respect to the x-axis.  Here's a screenshot from the pdf:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-4gwfbMgeFyE/TgdOmhBP7kI/AAAAAAAABqo/Crh3tTkSmAM/s1600/Screen%2Bshot%2B2011-06-26%2Bat%2B11.21.44%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 210px;" src="http://3.bp.blogspot.com/-4gwfbMgeFyE/TgdOmhBP7kI/AAAAAAAABqo/Crh3tTkSmAM/s320/Screen%2Bshot%2B2011-06-26%2Bat%2B11.21.44%2BAM.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5622549083400957506" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(Note, he uses capital X and Y for the second set of coordinates).&lt;br /&gt;&lt;br /&gt;In the &lt;code&gt;u,v&lt;/code&gt; system, the point &lt;code&gt;P&lt;/code&gt; has coordinates &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;u = r cos(&amp;phi;)&lt;br /&gt;v = r sin(&amp;phi;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;In the &lt;code&gt;x,y&lt;/code&gt; system the coordinates are:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x = r cos(&amp;phi; + &amp;theta;)&lt;br /&gt;y = r sin(&amp;phi; + &amp;theta;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;We remember (my post &lt;a href="http://telliott99.blogspot.com/2010/04/sums-of-sines-and-cosines.html"&gt;here&lt;/a&gt;) that:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;sin(s+t) = sin s cos t + cos s sin t&lt;br /&gt;cos(s+t) = cos s cos t - sin s sin t&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Hence:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;x = r cos(&amp;phi;) cos(&amp;theta;) - r sin(&amp;phi;) sin(&amp;theta;)&lt;br /&gt;  = u cos(&amp;theta;) - v sin(&amp;theta;)&lt;br /&gt;&lt;br /&gt;y = r sin(&amp;phi;) cos(&amp;theta;) + r cos(&amp;phi;) sin(&amp;theta;)&lt;br /&gt;  = v cos(&amp;theta) + u sin(&amp;theta;)&lt;br /&gt;  = u sin(&amp;theta) + v cos(&amp;theta;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Now, consider the hyperbola:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;xy = 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Rewrite this in terms of &lt;code&gt;u,v&lt;/code&gt; and multiply, giving 4 terms&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;+ u cos(&amp;theta;) u sin(&amp;theta;)&lt;br /&gt;+ u cos(&amp;theta;) v cos(&amp;theta;)&lt;br /&gt;- u sin(&amp;theta;) v sin(&amp;theta;)&lt;br /&gt;- v sin(&amp;theta;) v cos(&amp;theta;)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;If &lt;code&gt;&amp;theta;&lt;/code&gt; equals &lt;code&gt;&amp;pi;/4&lt;/code&gt;, then &lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;cos(&amp;theta;) = sin(&amp;theta;) = 1/&amp;radic;2&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The two middle terms drop out and leave us with:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;u&lt;sup&gt;2&lt;/sup&gt;/2 - v&lt;sup&gt;2&lt;/sup&gt;/2 = 1&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;If the middle terms don't cancel, we're left with a mixture including some fraction of&lt;br /&gt;u&lt;sup&gt;2&lt;/sup&gt;/2, v&lt;sup&gt;2&lt;/sup&gt;/2, and u times v.&lt;br /&gt;&lt;br /&gt;Note:  we rotated the coordinate system counter-clockwise, which has the effect of rotating the plot clockwise, when the coordinate system is viewed in standard orientation.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-189122277697401453?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/189122277697401453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=189122277697401453' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/189122277697401453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/189122277697401453'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/06/different-views-same-parabola.html' title='Different views, same hyperbola'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-OLbJUi9wrUU/TgdPaXPLlgI/AAAAAAAABqw/EqukeKSwhDg/s72-c/Screen%2Bshot%2B2011-06-26%2Bat%2B11.24.38%2BAM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-7799564869063737012</id><published>2011-06-25T08:22:00.004-04:00</published><updated>2011-06-28T19:44:31.001-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>One more thing about 3x3 determinants</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;While we're on the topic of determinants (see yesterday's &lt;a href="http://telliott99.blogspot.com/2011/06/cramers-rule-calculation.html"&gt;post&lt;/a&gt;), rather than pounding on arithmetic drills, the other thing I would show algebra students is that you can use any row or column to set up the computation.  That can be useful if one choice contains zeros.&lt;br /&gt;&lt;br /&gt;The standard approach uses the top row:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;a b c&lt;br /&gt;d e f&lt;br /&gt;g h i&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;And the determinant is:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;a(ei-hf) - b(di-fg) + c(dh-eg)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Where the sign of the second term is negative by the checkerboard rule:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;+ - +&lt;br /&gt;- + -&lt;br /&gt;+ - +&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Multiplying out we obtain:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;aei - afh - bdi + bfg + cdh - ceg&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The 6 terms contain three components, each taken from a different row and column.  For example, the components of &lt;code&gt;bdi&lt;/code&gt; are from:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;b = (1,2)&lt;br /&gt;d = (2,1)&lt;br /&gt;i = (3,3)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The checkerboard rule makes the sign come out correctly.  &lt;br /&gt;&lt;br /&gt;If we're working with the top row or the middle column and so processing &lt;code&gt;b x (di - fg)&lt;/code&gt; or &lt;code&gt;d x (bi - ch)&lt;/code&gt;, we'll need the minus sign;  whereas if we're obtaining this term from &lt;code&gt;i x (ae - bd)&lt;/code&gt; we already have a minus sign.&lt;br /&gt;&lt;br /&gt;Let's try using the last row.  We have:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;a b c&lt;br /&gt;d e f&lt;br /&gt;g h i&lt;br /&gt;&lt;br /&gt;g(bf - ce) - h(af - cd) + i(ae - bd)&lt;br /&gt;bfg - cdg - afh + cdh + aei - bdi&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Compare with the first example to see that all the terms are present.&lt;br /&gt;&lt;br /&gt;Can we do it by the diagonal?  Try &lt;code&gt;ceg&lt;/code&gt;:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;c(dh - eg) - e(ai - cg) + g(bf - ce)&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Nope.  Some terms are correct, but some are duplicates.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8953369623923024563-7799564869063737012?l=telliott99.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://telliott99.blogspot.com/feeds/7799564869063737012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8953369623923024563&amp;postID=7799564869063737012' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7799564869063737012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8953369623923024563/posts/default/7799564869063737012'/><link rel='alternate' type='text/html' href='http://telliott99.blogspot.com/2011/06/one-more-thing-about-3x3-determinants.html' title='One more thing about 3x3 determinants'/><author><name>telliott99</name><uri>http://www.blogger.com/profile/01151844786921735933</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://bp2.blogger.com/_39NGKVWYg3o/SB97WaOEf9I/AAAAAAAAAAU/Nl4eBrSdaME/S220/te.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8953369623923024563.post-2233889030853618189</id><published>2011-06-24T08:00:00.000-04:00</published><updated>2011-06-24T12:34:19.006-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='simple Python'/><category scheme='http://www.blogger.com/atom/ns#' term='simple math'/><title type='text'>Cramer's rule calculation</title><content type='html'>&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;We have algebra homework that involves using &lt;a href="http://en.wikipedia.org/wiki/Cramer%27s_rule"&gt;Cramer's rule&lt;/a&gt; to solve not only 2 x 2 but also 3 x 3 systems.  It seems kind of silly since this method is overkill for 2 x 2, and would never be used for 4 x 4 or larger.&lt;br /&gt;&lt;br /&gt;(Note on the wikipedia article, start about halfway down, where it says "Explicit formulas for small systems".)&lt;br /&gt;&lt;br /&gt;Also, and this gets closer to the point, drilling by solving 3 x 3 matrices is not really about the rule, which is pretty simple.  It's about making an easy problem harder by stuffing a lot of arithmetic into it.  And to me, that is symptomatic of a big difficulty with math education as I'm encountering it through my son.  Computers are much better at computing sums than humans.  It's just silly to drill students on arithmetic.  If you want to do something complicated, why not derive Cramer's rule?&lt;br /&gt;&lt;br /&gt;So, I decided to write a solver for 3 x 3 systems in Python.  I wouldn't say it's thoroughly debugged yet, so let me know if you run into a problem.  With the example shown, I did get the same answer as this online &lt;a href="http://www.analyzemath.com/Calculators/Calculator_syst_eq.html"&gt;calculator&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first code segment contains the equations explicitly entered as an array.  I'm sure you know how to modify it to read input from a file.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;test.py&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;import numpy as np&lt;br /&gt;import Cramer&lt;br /&gt;&lt;br /&gt;def test_Cramer():&lt;br /&gt;    L = [2, 3, 0, 5,&lt;br /&gt;         1, 1, 1, 3,&lt;br /&gt;         2,-1, 3, 7]   &lt;br /&gt;    A = np.array(L)&lt;br /&gt;    A.shape = (3,4)&lt;br /&gt;    result = Cramer.solve(A)&lt;br /&gt;    if result:&lt;br /&gt;        x,y,z = result&lt;br /&gt;        print 'solution'&lt;br /&gt;        print 'x =', x&lt;br /&gt;        print 'y =', y&lt;br /&gt;        print 'z =', z, '\n'&lt;br /&gt;        Cramer.check(A,x,y,z)&lt;br /&gt;&lt;br /&gt;test_Cramer()&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;The output looks like this:&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#b0ffff" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;&gt; python test.py &lt;br /&gt;solve&lt;br /&gt;[[ 2  3  0  5]&lt;br /&gt; [ 1  1  1  3]&lt;br /&gt; [ 2 -1  3  7]] &lt;br /&gt;&lt;br /&gt;compute 3 x 3 det of&lt;br /&gt;[[ 2  3  0]&lt;br /&gt; [ 1  1  1]&lt;br /&gt; [ 2 -1  3]]&lt;br /&gt;D =  5 &lt;br /&gt;&lt;br /&gt;compute 3 x 3 det of&lt;br /&gt;[[ 5  3  0]&lt;br /&gt; [ 3  1  1]&lt;br /&gt; [ 7 -1  3]]&lt;br /&gt;Dx =  14 &lt;br /&gt;&lt;br /&gt;compute 3 x 3 det of&lt;br /&gt;[[2 5 0]&lt;br /&gt; [1 3 1]&lt;br /&gt; [2 7 3]]&lt;br /&gt;Dy =  -1 &lt;br /&gt;&lt;br /&gt;compute 3 x 3 det of&lt;br /&gt;[[ 2  3  5]&lt;br /&gt; [ 1  1  3]&lt;br /&gt; [ 2 -1  7]]&lt;br /&gt;Dz =  2 &lt;br /&gt;&lt;br /&gt;solution&lt;br /&gt;x = 2.8&lt;br /&gt;y = -0.2&lt;br /&gt;z = 0.4 &lt;br /&gt;&lt;br /&gt;check&lt;br /&gt;row 0 = [2 3 0 5]&lt;br /&gt;2.0*2.8 + 3.0*-0.2 + 0.0*0.4  = 5.0 &lt;br /&gt;&lt;br /&gt;row 1 = [1 1 1 3]&lt;br /&gt;1.0*2.8 + 1.0*-0.2 + 1.0*0.4  = 3.0 &lt;br /&gt;&lt;br /&gt;row 2 = [ 2 -1  3  7]&lt;br /&gt;2.0*2.8 + -1.0*-0.2 + 3.0*0.4  = 7.0&lt;/pre&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Cramer.py&lt;/code&gt;&lt;br /&gt;&lt;div style="overflow-x: scroll "&gt;&lt;br /&gt;&lt;table bgcolor="#ffffb0" border="0" width="100%" padding="4"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=" hidden;font-family:monaco;"&gt;import numpy as np&lt;br /&gt;&lt;br /&gt;def det2x2(A, v=False):&lt;br /&gt;    if v:  print 'compute 2 x 2 det of'&lt;br /&gt;    if v:  print A&lt;br /&gt;    assert A.shape == (2,2)&lt;br /&gt;    return A[0][0]*A[1][1] - A[0][1]*A[1][0]&lt;br /&gt;&lt;br /&gt;def det3x3(A):&lt;br /&gt;    print 'compute 3 x 3 det of'&lt;br /&gt;    print A&lt;br /&gt;    assert A.shape == (3,3)&lt;br /&gt;    a,b,c = A[0]&lt;br /&gt;    c1 = a * det2x2(A[1:3,[1,2]])&lt;br /&gt;    c2 = b * det2x2(A[1:3,[0,2]])&lt;br /&gt;    c3 = c * det2x2(A[1:3,[0,1]])&lt;br /&gt;    return c1 - c2 + c3&lt;br /&gt;         &lt;br /&gt;def solve(A):&lt;br /&gt;    print 'solve'&lt;br /&gt;    print A, '\n'&lt;br /&gt;    assert A.shape == (3,4)&lt;br /&gt;    D = det3x3(A[:,:3])&lt;br /&gt;    print 'D = ', D, '\n'&lt;br /&gt;    if D == 0:&lt;br /&gt;        print 'no so
