<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>chriscoughlin.com</title>
	<atom:link href="http://www.chriscoughlin.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.chriscoughlin.com</link>
	<description>stochastic arrangement of 1&#039;s and 0&#039;s</description>
	<lastBuildDate>Fri, 20 Jan 2012 00:07:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Thoughts On OST&#8217;s Python Programming Certificate</title>
		<link>http://www.chriscoughlin.com/2011/12/thoughts-on-osts-python-programming-certificate/</link>
		<comments>http://www.chriscoughlin.com/2011/12/thoughts-on-osts-python-programming-certificate/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 23:06:54 +0000</pubDate>
		<dc:creator>crc</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.chriscoughlin.com/?p=258</guid>
		<description><![CDATA[I completed the four-course Python Programming Certificate program at O&#8217;Reilly School of Technology a few weeks ago and now that I&#8217;ve had a while to think about it I thought it might be useful for anyone else considering the program to &#8230; <a href="http://www.chriscoughlin.com/2011/12/thoughts-on-osts-python-programming-certificate/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I completed the four-course <a title="Python Programming Certificate @ OST" href="http://www.oreillyschool.com/certificates/python-programming.php">Python Programming Certificate</a> program at <a title="O'Reilly School Of Technology" href="http://www.oreillyschool.com/">O&#8217;Reilly School of Technology</a> a few weeks ago and now that I&#8217;ve had a while to think about it I thought it might be useful for anyone else considering the program to jot down a couple of paragraphs, especially since when I was first looking at the program I wasn&#8217;t able to find anything about people that had gone through the whole thing.</p>
<p>First, a word about where I&#8217;m coming from.  I&#8217;d written some Python code at/for the day job for a year or two prior, and felt fairly comfortable with the language before I started the program.  I wasn&#8217;t really looking for a certificate à la <a title="Java Certification" href="http://java.sun.com/new2java/articles/certification.html">Java certification</a>, I was mainly looking for something that&#8217;d give me more Python experience and make me feel comfortable in saying I &#8220;knew&#8221; Python.</p>
<p>All in all I quite enjoyed the program.  There&#8217;s plenty of details online about how OST courses work but in a nutshell it&#8217;s read a lesson and complete exercises as you go, then a quiz or two with three or four questions and a programming assignment to turn in.  The assignment&#8217;s usually 100-odd lines of code (not including unit tests), with the final assignments at the end of each course a little more involved.  Each course has 15 or so lessons, and OST says you should expect to spend about 40 hours total on each course.  I didn&#8217;t time my progress but I don&#8217;t think it took me that long, but your mileage may differ.</p>
<p>Of the two I very much prefer the assignments &#8211; I found the quizzes a little too &#8220;copy-paste&#8221; from the lesson, and in a lot of cases it seemed as though you had to be fairly precise with your answers&#8217; wording to get it right.  I found the wording for the quizzes to be a little fuzzy occasionally so that I had a bit of a tough time figuring out exactly what the question was asking.</p>
<p>The assignments on the other hand were pretty enjoyable for the most part &#8211; you&#8217;re given a task to code and some criteria to meet, then you&#8217;re more or less left to your own devices.  The instructors were pretty good about pointing out places your solution could be improved, alternate ways of doing things, and so on.</p>
<p>After you&#8217;re taught the basics of Python, the rest of the coursework is primarily looking at the use of specific modules in the standard library.  Some modules get more of a workout than others, so for example there are several lessons on both Tkinter and MySQL.</p>
<p>By far my favorite aspect of the program was the enforced unit testing and test-driven development process.  Almost at the beginning you&#8217;re introduced to unittest, and once the preliminary introductions are out of the way you&#8217;re expected to use TDD for all the assignments.  In fact if I remember correctly you&#8217;re even told at one point that your assignments won&#8217;t get a passing grade without unit tests.  I found this to be the most valuable part of the coursework &#8211; by the time I was done unittest and TDD were completely second nature to me, and it&#8217;s probably the most important thing I picked up from the program.</p>
<p>If you&#8217;re already a hard-core Pythonista I don&#8217;t think there&#8217;s much in this program you won&#8217;t already know.  On the other hand, if you&#8217;re looking to get a little workout with Python or coming to it fresh I can definitely recommend it.  And in case you&#8217;re wondering, if you complete all four courses you do indeed get a certificate, suitable for framing.  :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chriscoughlin.com/2011/12/thoughts-on-osts-python-programming-certificate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Delivering wxPython Applications With PyInstaller</title>
		<link>http://www.chriscoughlin.com/2011/10/delivering-wxpython-applications-with-pyinstaller/</link>
		<comments>http://www.chriscoughlin.com/2011/10/delivering-wxpython-applications-with-pyinstaller/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 21:12:00 +0000</pubDate>
		<dc:creator>crc</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.chriscoughlin.com/?p=195</guid>
		<description><![CDATA[Questions like &#8220;What GUI should I use with Python?&#8221; and &#8220;What&#8217;s the best way to make a standalone Python app?&#8221; come up on Reddit and Stack Overflow pretty frequently.  Having put together a standalone Python application a couple of months &#8230; <a href="http://www.chriscoughlin.com/2011/10/delivering-wxpython-applications-with-pyinstaller/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Questions like &#8220;What GUI should I use with Python?&#8221; and &#8220;What&#8217;s the best way to make a standalone Python app?&#8221; come up on <a title="Python Reddit" href="http://www.reddit.com/r/Python/">Reddit</a> and <a title="Questions tagged 'Python' on Stack Overflow" href="http://stackoverflow.com/questions/tagged/python">Stack Overflow</a> pretty frequently.  Having put together a standalone Python application <a title="First post about PODBrowser" href="http://www.chriscoughlin.com/2011/08/font-errors-pyinstaller-matplotlib/">a couple of months ago</a>, I thought I&#8217;d post something about my experiences.</p>
<p>PODBrowser is a simple desktop application I put together as part of a larger project to revamp a handbook of <a title="American Society For Nondestructive Testing's POD Overview" href="http://www.asnt.org/publications/materialseval/basics/jan98basics/jan98basics.htm">Probability Of Detection (POD)</a> curves.  The hows and whys of POD don&#8217;t really concern us here, all that matters is that I&#8217;m writing a program that lets the user easily preview and plot technical data from 500+ Excel files.  The files are organized by folders so that the root data folder has sub-folders for every technique used; inside each technique folder is one or more sub-folders for every sample that was inspected by that technique.</p>
<p>PODBrowser searches through its data folder and organizes data by technique and sample.  When the user selects an Excel file to preview, a new window pops up with the Excel file in question previewing the first sheet in the file that isn&#8217;t a chart (PODBrowser skips the &#8220;Chart1&#8243; sheets in these data files).  The user can select any of the sheets in the spreadsheet to preview, and plot the POD curve for the given sheet.  The end goal was an application that could be distributed as a CD in the back of the hardcopy POD Handbook we were contracted to update, or as a promotional USB flash drive giveaway at conferences and trade shows.</p>
<p>I used three third party Python libs to write PODBrowser:  <a title="wxPython.org" href="http://www.wxpython.org/">wxPython</a> as the UI toolkit, <a title="xlrd" href="http://www.lexicon.net/sjmachin/xlrd.htm">xlrd</a> to read the Excel files, and <a title="matplotlib.sf.net" href="http://matplotlib.sourceforge.net/">matplotlib</a> to produce the plots.  All three work great with <a title="PyInstaller.org" href="http://www.pyinstaller.org/">PyInstaller</a>, my Python standalone creator of choice.  I went with PyInstaller over <a title="py2exe.org" href="http://www.py2exe.org/">py2exe</a> because PyInstaller handles the whole <a title="PyInstaller's discussion of Python 2.6 apps" href="http://www.pyinstaller.org/wiki/Python26Win">DLL mess</a> that otherwise crops up in bundling Python 2.6+ applications, and because it knows how to handle matplotlib without any tinkering on my part.</p>
<p>Once you&#8217;ve got PyInstaller installed, the next step is to <a title="Creating spec files for PyInstaller" href="http://www.pyinstaller.org/export/latest/tags/1.5.1/doc/Manual.html?format=raw#create-a-spec-file-for-your-project">create the spec file</a> for your application.  PyInstaller&#8217;s docs are pretty good for getting going on this step; the only options I used were <code>-w</code> to keep the cmd console hidden and <code>--icon</code> to specify the icon I&#8217;d made for the final product.  Once you get the spec file working there&#8217;s not much need to ever visit it again unless your project changes or you want to change the final product; I got in the habit of thinking of it as a <code>Makefile</code> of sorts and</p>
<pre>python Build.py specfile</pre>
<p>as my compilation. I actually had more trouble putting together a decent icon for PODBrowser under Windows than I ever did building the standalone with PyInstaller.</p>
<p>I went with wxPython over say PyQt or Tkinter mainly because I&#8217;m more familiar with it, and because I like that wxWidgets uses the underlying native toolkit where possible.  You can substitute your own UI toolkit of choice over wxPython, PyInstaller works with most of them.  Here&#8217;s what the final product looked like on a couple of platforms:</p>
<div id="portfolio-slideshow0" class="portfolio-slideshow">
	<div class="slideshow-next slideshow-content">
			<a href="javascript: void(0);" class="slideshow-next"><img class="psp-active" data-img="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Ubuntu-Linux-I.png" src="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Ubuntu-Linux-I.png" height="370" width="742" alt="PODBrowser Ubuntu Linux I" /><noscript><img src="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Ubuntu-Linux-I.png" height="370" width="742" alt="PODBrowser Ubuntu Linux I" /></noscript></a><div class="slideshow-meta"><p class="slideshow-title">PODBrowser Ubuntu Linux I</p></div></div>
			<div class="not-first slideshow-next slideshow-content">
			<a href="javascript: void(0);" class="slideshow-next"><img class="psp-active" data-img="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Ubuntu-Linux-II.png" src="http://www.chriscoughlin.com/wp-content/plugins/portfolio-slideshow/img/tiny.png" height="752" width="961" alt="PODBrowser Ubuntu Linux II" /><noscript><img src="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Ubuntu-Linux-II.png" height="752" width="961" alt="PODBrowser Ubuntu Linux II" /></noscript></a><div class="slideshow-meta"><p class="slideshow-title">PODBrowser Ubuntu Linux II</p></div></div>
			<div class="not-first slideshow-next slideshow-content">
			<a href="javascript: void(0);" class="slideshow-next"><img class="psp-active" data-img="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Windows-7-I.png" src="http://www.chriscoughlin.com/wp-content/plugins/portfolio-slideshow/img/tiny.png" height="393" width="699" alt="PODBrowser Windows 7 I" /><noscript><img src="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Windows-7-I.png" height="393" width="699" alt="PODBrowser Windows 7 I" /></noscript></a><div class="slideshow-meta"><p class="slideshow-title">PODBrowser Windows 7 I</p></div></div>
			<div class="not-first slideshow-next slideshow-content">
			<a href="javascript: void(0);" class="slideshow-next"><img class="psp-active" data-img="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Windows-7-II.png" src="http://www.chriscoughlin.com/wp-content/plugins/portfolio-slideshow/img/tiny.png" height="657" width="1103" alt="PODBrowser Windows 7 II" /><noscript><img src="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-Windows-7-II.png" height="657" width="1103" alt="PODBrowser Windows 7 II" /></noscript></a><div class="slideshow-meta"><p class="slideshow-title">PODBrowser Windows 7 II</p></div></div>
			<div class="not-first slideshow-next slideshow-content">
			<a href="javascript: void(0);" class="slideshow-next"><img class="psp-active" data-img="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-XP-I.png" src="http://www.chriscoughlin.com/wp-content/plugins/portfolio-slideshow/img/tiny.png" height="218" width="547" alt="PODBrowser XP I" /><noscript><img src="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-XP-I.png" height="218" width="547" alt="PODBrowser XP I" /></noscript></a><div class="slideshow-meta"><p class="slideshow-title">PODBrowser XP I</p></div></div>
			<div class="not-first slideshow-next slideshow-content">
			<a href="javascript: void(0);" class="slideshow-next"><img class="psp-active" data-img="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-XP-II.png" src="http://www.chriscoughlin.com/wp-content/plugins/portfolio-slideshow/img/tiny.png" height="654" width="961" alt="PODBrowser XP II" /><noscript><img src="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser-XP-II.png" height="654" width="961" alt="PODBrowser XP II" /></noscript></a><div class="slideshow-meta"><p class="slideshow-title">PODBrowser XP II</p></div></div>
			</div><!--#portfolio-slideshow--></div><!--#slideshow-wrapper-->
<p>(Those parentheses are actually part of the original Excel filenames &#8211; I have no idea what the reasoning was behind that.)</p>
<p>The final tally in distribution size was around 45MB, including some basic documentation but not including the Excel data files (which was another 130MB, give or take).  Of that, about 8MB was for matplotlib, another 4MB for matplotlib fonts and toolbar icons, 10-15MB for wxPython, and only about 200kB or so for xlrd.  Ballpark, if you weren&#8217;t using matplotlib and xlrd, you&#8217;re looking at around a 30MB distributable.  You can use <a title="UPX.sf.net" href="http://upx.sf.net/">UPX</a> to bring that final size down, but for this application I really only needed it small enough to fit on a CD and/or thumb drive handed out at conferences so 45MB was small enough in this case.  I also put together a setup.msi Windows Installer package with <a title="Advanced Installer (commercial MSI builder)" href="http://www.advancedinstaller.com/">Advanced Installer</a>; the final tally there including some brief installation instructions was 43MB.</p>
<p>If you&#8217;d like to see the final result in action, here&#8217;s a link to an <a title="ZIP of PODBrowser Python code" href="http://www.chriscoughlin.com/wp-content/uploads/2011/10/PODBrowser.zip">archive of the source code</a>. Also included in there is a copy of the PyInstaller spec file I used to make it a standalone application under Windows.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chriscoughlin.com/2011/10/delivering-wxpython-applications-with-pyinstaller/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Font Errors:  PyInstaller + matplotlib</title>
		<link>http://www.chriscoughlin.com/2011/08/font-errors-pyinstaller-matplotlib/</link>
		<comments>http://www.chriscoughlin.com/2011/08/font-errors-pyinstaller-matplotlib/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 17:31:16 +0000</pubDate>
		<dc:creator>crc</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.chriscoughlin.com/?p=156</guid>
		<description><![CDATA[If you ever want to deliver a standalone Python-based app that doesn&#8217;t require a full-blown Python install, have a look at PyInstaller.  It&#8217;s just about the most painless way I know of to do it and it supports a ton &#8230; <a href="http://www.chriscoughlin.com/2011/08/font-errors-pyinstaller-matplotlib/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you ever want to deliver a standalone Python-based app that doesn&#8217;t require a full-blown Python install, have a look at <a title="PyInstaller Page" href="http://www.pyinstaller.org/">PyInstaller</a>.  It&#8217;s just about the most painless way I know of to do it and it supports a ton of <a title="Supported Python Packages - PyInstaller" href="http://www.pyinstaller.org/wiki/SupportedPackages">Python libs right out of the box</a>.  If you don&#8217;t see your package listed there, go ahead and try it since there&#8217;s a good chance it&#8217;ll work anyway- I found that the Excel spreadsheet lib <a title="Python Package Index page for xlrd" href="http://pypi.python.org/pypi/xlrd">xlrd</a> works without a hitch, for example.</p>
<p>One thing I did discover this morning though about <a title="matplotlib Python plotting package" href="http://matplotlib.sourceforge.net/">matplotlib</a> &#8211; on Windows at least (I haven&#8217;t confirmed for other platforms), matplotlib keeps a font cache under the .matplotlib folder that points to font installations.  I put together a <a title="wxPython Python UI toolkit" href="http://wxpython.org/">wxPython</a> + matplotlib + xlrd app that worked fine with PyInstaller but I couldn&#8217;t figure out why it wouldn&#8217;t plot data it pulled from the Excel spreadsheets.  Looking at the debug messages, matplotlib seemed to be complaining that it couldn&#8217;t find the Vera font; PyInstaller knows to include the fonts with the frozen app so it looked like matplotlib wasn&#8217;t looking in the right place.</p>
<p>It turned out matplotlib&#8217;s font cache was pointing to a non-existent folder &#8211; delete the cache and the app worked as advertised on next startup.  In my case, it hit me because I used to have matplotlib installed as part of my Python installation but I later removed it; but you might also run into it if you&#8217;ve run and removed other matplotlib-based applications.  I&#8217;m sure there&#8217;s a better fix than the one I&#8217;ve outlined but I thought I&#8217;d post my findings in case anyone else comes across this same problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chriscoughlin.com/2011/08/font-errors-pyinstaller-matplotlib/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SWIG and Python</title>
		<link>http://www.chriscoughlin.com/2011/08/swig-and-python/</link>
		<comments>http://www.chriscoughlin.com/2011/08/swig-and-python/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 16:04:30 +0000</pubDate>
		<dc:creator>crc</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.chriscoughlin.com/?p=124</guid>
		<description><![CDATA[I originally wrote this up earlier this year as part of a how-to on creating plugins for NDIToolbox.  I thought it might be worth posting it on its own in case anyone&#8217;s looking for a quick intro to using SWIG &#8230; <a href="http://www.chriscoughlin.com/2011/08/swig-and-python/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>I originally wrote this up earlier this year as part of a how-to on creating plugins for <a title="TRI's NDIToolbox Site" href="http://www.nditoolbox.com">NDIToolbox</a>.  I thought it might be worth posting it on its own in case anyone&#8217;s looking for a quick intro to using <a title="Simplified Wrapper and Interface Generator" href="http://www.swig.org/">SWIG</a> with Python and C++.  Among other things, SWIG is great if you started with a pure Python program but find yourself needing a bit of a speed boost:  just take the number-crunching or other expensive code and replace it with C or C++.</em></p>
<h2>Pure Python Application</h2>
<p><a href="http://www.chriscoughlin.com/wp-content/uploads/2011/08/hhcoils_s.jpg"><img class="alignleft size-medium wp-image-140" title="Helmholtz Coils" src="http://www.chriscoughlin.com/wp-content/uploads/2011/08/hhcoils_s-300x198.jpg" alt="Structure of Helmholtz coils - two identical coils carrying the same current" width="300" height="198" /></a>To demonstrate how to build and structure a Python-only toolkit for NDIToolbox we’ll build a <a title="Wikipedia's Entry On Helmholtz Coils" href="http://en.wikipedia.org/wiki/Helmholtz_coil">Helmholtz coils</a> calculator to calculate the magnetic field produced by a pair of identical coils of radius <em>a</em>, number of turns <em>N</em>, and each carrying a current <em>I</em>. If the coils are in opposition (either the coils are wound in opposite directions or the coils’ currents are in opposite direction), their magnetic fields interact to create a maximum at the center.</p>
<h3>Organization</h3>
<p>Following our recommended approach, we’re going to develop our main logic and user interface separately from the toolkit interface. We’ll have one Python file for the logic hhcoils.py that has a class HelmholtzCoils in which all our calculations are contained. We’ve decided to do a simple wxPython user interface, hhcoils_ui.py, that’s responsible for taking user input and reporting the results of our calculator back to the user. Finally, our toolkit interface with NDIToolbox will be in a third Python file hhcoils_toolkit.py.</p>
<p><em>(Note-I&#8217;m skipping the toolkit for this post, and the UI&#8217;s been replaced with a simple script that demonstrates function.)</em></p>
<h3>Logic</h3>
<p>Our hhcoils.py file that handles all the calculations is as follows. By itself it’s not very interesting but it helps to illustrate a simple way of structuring your application as both a standalone and as a toolkit.</p>
<div id="gist-1162492" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c">#!/usr/bin/env python</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="sd">&#39;&#39;&#39; HelmholtzCoils - simple magnetic field calculator (originally used to demo plugin development in NDIToolbox)</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="sd">Chris Coughlin (TRI/Austin, Inc.)</span></div><div class='line' id='LC6'><span class="sd">&#39;&#39;&#39;</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="kn">import</span> <span class="nn">math</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'><span class="k">class</span> <span class="nc">HelmholtzCoils</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Calculates the magnetic field produced by a pair of Helmholtz coils wound in opposition&#39;&#39;&#39;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">mu_0</span> <span class="o">=</span> <span class="mf">4.</span><span class="o">*</span><span class="n">math</span><span class="o">.</span><span class="n">pi</span><span class="o">*</span><span class="mf">1e-7</span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">turns_per_coil</span><span class="p">,</span> <span class="n">current_per_coil</span><span class="p">,</span> <span class="n">coil_radius</span><span class="p">):</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">N</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">turns_per_coil</span><span class="p">)</span> <span class="c"># Turns per coil</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">I</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">current_per_coil</span><span class="p">)</span> <span class="c"># Current (A) per coil</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">coil_radius</span><span class="p">)</span> <span class="c"># Common radius (m) of coils</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">lhcoil_position</span> <span class="o">=</span> <span class="o">-</span><span class="bp">self</span><span class="o">.</span><span class="n">a</span><span class="o">/</span><span class="mf">2.</span> <span class="c"># Position of left coil (m), defined as a/2</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">rhcoil_position</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span><span class="o">/</span><span class="mf">2.</span> <span class="c"># Position of right coil (m), defined as a/2</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">geometry_correction</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">coil_position</span><span class="p">,</span> <span class="n">position</span><span class="p">):</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Geometry correction for magnetic field calcs&#39;&#39;&#39;</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">math</span><span class="o">.</span><span class="n">pow</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">math</span><span class="o">.</span><span class="n">pow</span><span class="p">(</span><span class="n">coil_position</span> <span class="o">-</span> <span class="n">position</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">/</span> <span class="n">math</span><span class="o">.</span><span class="n">pow</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">a</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">)</span></div><div class='line' id='LC24'><br/></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">H</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">position</span><span class="p">):</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Magnetic field at position (m) in A/m&#39;&#39;&#39;</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">lh_geometry_factor</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">geometry_correction</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lhcoil_position</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">rh_geometry_factor</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">geometry_correction</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">rhcoil_position</span><span class="p">,</span> <span class="n">position</span><span class="p">)</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">total_geometry_factor</span> <span class="o">=</span> <span class="n">lh_geometry_factor</span> <span class="o">+</span> <span class="n">rh_geometry_factor</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">N</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">I</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span><span class="p">))</span> <span class="o">*</span> <span class="n">total_geometry_factor</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">centerH</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Magnetic field at dead center of coils&#39;&#39;&#39;</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">B</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">position</span><span class="p">):</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Flux density at position (m) in mT&#39;&#39;&#39;</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">HelmholtzCoils</span><span class="o">.</span><span class="n">mu_0</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">H</span><span class="p">(</span><span class="n">position</span><span class="p">)</span><span class="o">*</span><span class="mi">1000</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">centerB</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Flux density at dead center of coils&#39;&#39;&#39;</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">B</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">B_mG</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">position</span><span class="p">):</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Flux density at position (m) in mG&#39;&#39;&#39;</span></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">B</span><span class="p">(</span><span class="n">position</span><span class="p">)</span> <span class="o">*</span> <span class="mf">1e4</span></div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC48'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">wirelength</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Length of wire (m) to make N turns of radius a&#39;&#39;&#39;</span></div><div class='line' id='LC50'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">coil_circumference</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">*</span> <span class="mf">2.</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">a</span></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">wire_per_coil</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">N</span><span class="p">)</span> <span class="o">*</span> <span class="n">coil_circumference</span></div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="mf">2.</span><span class="o">*</span><span class="n">wire_per_coil</span></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">awg_recommendation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Returns a recommendation for AWG wire gauge to use for the coils for currents between</span></div><div class='line' id='LC56'><span class="sd">        0.0125 and 15 Amps.  Conservative estimate, returns 0 as recommendation for currents </span></div><div class='line' id='LC57'><span class="sd">        outside this range.&#39;&#39;&#39;</span></div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">gauge_current</span> <span class="o">=</span> <span class="p">{</span><span class="mi">10</span><span class="p">:</span><span class="mi">15</span><span class="p">,</span> <span class="mi">11</span><span class="p">:</span><span class="mi">10</span><span class="p">,</span> <span class="mi">14</span><span class="p">:</span><span class="mi">5</span><span class="p">,</span> <span class="mi">17</span><span class="p">:</span><span class="mf">2.5</span><span class="p">,</span> <span class="mi">20</span><span class="p">:</span><span class="mf">1.5</span><span class="p">,</span> <span class="mi">21</span><span class="p">:</span><span class="mf">1.0</span><span class="p">,</span> <span class="mi">22</span><span class="p">:</span><span class="mf">0.75</span><span class="p">,</span> <span class="mi">24</span><span class="p">:</span><span class="mf">0.5</span><span class="p">,</span></div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="mi">27</span><span class="p">:</span><span class="mf">0.25</span><span class="p">,</span> <span class="mi">30</span><span class="p">:</span><span class="mf">0.125</span><span class="p">,</span> <span class="mi">31</span><span class="p">:</span><span class="mf">0.100</span><span class="p">,</span> <span class="mi">32</span><span class="p">:</span><span class="mf">0.075</span><span class="p">,</span> <span class="mi">34</span><span class="p">:</span><span class="mf">0.050</span><span class="p">,</span> <span class="mi">37</span><span class="p">:</span><span class="mf">0.025</span><span class="p">,</span> <span class="mi">40</span><span class="p">:</span><span class="mf">0.0125</span><span class="p">}</span></div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">delta</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="s">&#39;inf&#39;</span><span class="p">)</span></div><div class='line' id='LC61'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">epsilon</span> <span class="o">=</span> <span class="mf">0.</span></div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">awg_rec</span> <span class="o">=</span> <span class="mi">0</span></div><div class='line' id='LC63'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">I</span> <span class="o">&gt;=</span> <span class="mf">0.0125</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">I</span> <span class="o">&lt;=</span> <span class="mi">15</span><span class="p">:</span></div><div class='line' id='LC64'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">for</span> <span class="n">gauge</span><span class="p">,</span> <span class="n">current</span> <span class="ow">in</span> <span class="n">gauge_current</span><span class="o">.</span><span class="n">items</span><span class="p">():</span></div><div class='line' id='LC65'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">epsilon</span> <span class="o">=</span> <span class="n">current</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">I</span></div><div class='line' id='LC66'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">epsilon</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">epsilon</span> <span class="o">&lt;</span> <span class="n">delta</span><span class="p">:</span></div><div class='line' id='LC67'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">delta</span> <span class="o">=</span> <span class="n">epsilon</span></div><div class='line' id='LC68'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">awg_rec</span> <span class="o">=</span> <span class="n">gauge</span></div><div class='line' id='LC69'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">awg_rec</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1162492/8dd7d5bfa5eff98caf1a40ff20f151def6910832/hhcoils.py" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1162492#file_hhcoils.py" style="float:right;margin-right:10px;color:#666">hhcoils.py</a>
            <a href="https://gist.github.com/1162492">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>To use the calculator in our user interface, we’ll create an HelmholtzCoils instance with the user’s choice for the number of turns <em>N</em> per coil, the current per coil <em>I</em>, and the coil radius (and the coil separation distance) <em>a</em>. So by way of a demonstration, let&#8217;s pretend the following is your UI&#8230;</p>
<pre>import hhcoils

if __name__ == "__main__":
    coils = hhcoils.HelmholtzCoils(100, 0.6, 0.8382)
    print("Field at centre (A/m) = {0}".format(coils.centerH()))
    print("Recommend {0} metres of {1} AWG wire.".format(coils.wirelength(),
        coils.awg_recommendation()))</pre>
<h2>Switching To C++</h2>
<p>As an example of how to use more than one language in developing your toolkit, suppose we’ve decided to swap out our Python Helmholtz coils engine for a new high-performance C++ engine. We’re happy with the user interface as-is and the toolkit interface works well; since we kept our layers separate we can simply swap the backends without any other changes.</p>
<h3>Logic</h3>
<p>We’ve decided that we need a high-performance C++ backend to increase the speed of our calculations. Investigating our options for interfacing C++ and Python we’ve decided to use <a title="Simplified Wrapper and Interface Generator" href="http://www.swig.org/">SWIG</a>. To use SWIG, we’ll first write our C++ Helmholtz coils calculator code; once we’re satisfied with it we’ll write a simple configuration file and let SWIG create a Python wrapper for us.</p>
<p>We’ve decided to have a single simple class HelmholtzCoils, defined in a header hhcoils.h and an implementation file hhcoils.cxx. Notice that we’re using exactly the same method names and arguments as our original Python engine – by doing this the changes are transparent to the GUI and we won’t have to make changes to hhcoils_ui.py. Since our GUI won’t be altered we also won’t have to update our toolkit interface, meaning that we can just drop the new engine into the hhcoils folder and the upgrade is complete. Current customers of our toolkit can do the same with their installations to take advantage of the new engine, or we could write a simple installer to automate the process for them.</p>
<div id="gist-1162649" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/* HelmholtzCoils - demonstrating separation of analysis and toolkit interface in NDIToolbox by creating a</span></div><div class='line' id='LC2'><span class="cm">simple magnetic field calculator</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="cm">Chris Coughlin (TRI/Austin, Inc.)</span></div><div class='line' id='LC5'><span class="cm">*/</span></div><div class='line' id='LC6'><span class="cp">#include &quot;hhcoils.h&quot;</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="k">const</span> <span class="kt">double</span> <span class="n">HelmholtzCoils</span><span class="o">::</span><span class="n">H</span><span class="p">(</span><span class="kt">double</span> <span class="n">position</span><span class="p">)</span> <span class="k">const</span><span class="p">{</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">lh_geometry_factor</span> <span class="o">=</span> <span class="n">geometry_correction</span><span class="p">(</span><span class="n">lhcoil_position</span><span class="p">,</span><span class="n">position</span><span class="p">);</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">rh_geometry_factor</span> <span class="o">=</span> <span class="n">geometry_correction</span><span class="p">(</span><span class="n">rhcoil_position</span><span class="p">,</span><span class="n">position</span><span class="p">);</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">total_geometry_factor</span> <span class="o">=</span> <span class="n">lh_geometry_factor</span> <span class="o">+</span> <span class="n">rh_geometry_factor</span><span class="p">;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="p">((</span><span class="n">N</span><span class="o">*</span><span class="n">I</span><span class="p">)</span><span class="o">/</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="n">a</span><span class="p">))</span><span class="o">*</span><span class="n">total_geometry_factor</span><span class="p">;</span></div><div class='line' id='LC13'><span class="p">}</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'><span class="k">const</span> <span class="kt">double</span> <span class="n">HelmholtzCoils</span><span class="o">::</span><span class="n">geometry_correction</span><span class="p">(</span><span class="k">const</span> <span class="kt">double</span> <span class="n">coil_position</span><span class="p">,</span> <span class="k">const</span> <span class="kt">double</span> <span class="n">position</span><span class="p">)</span> <span class="k">const</span><span class="p">{</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">pow</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">pow</span><span class="p">(</span><span class="n">coil_position</span> <span class="o">-</span> <span class="n">position</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span> <span class="o">/</span> <span class="n">pow</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="mi">2</span><span class="p">),</span> <span class="o">-</span><span class="mf">1.5</span><span class="p">);</span></div><div class='line' id='LC17'><span class="p">}</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'><span class="k">const</span> <span class="kt">double</span> <span class="n">HelmholtzCoils</span><span class="o">::</span><span class="n">wirelength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">coil_circumference</span> <span class="o">=</span> <span class="n">M_PI</span><span class="o">*</span><span class="mi">2</span><span class="o">*</span><span class="n">a</span><span class="p">;</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">wire_per_coil</span> <span class="o">=</span> <span class="n">N</span><span class="o">*</span><span class="n">coil_circumference</span><span class="p">;</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="mi">2</span><span class="o">*</span><span class="n">wire_per_coil</span><span class="p">;</span></div><div class='line' id='LC23'><span class="p">}</span></div><div class='line' id='LC24'><br/></div><div class='line' id='LC25'><span class="k">const</span> <span class="kt">double</span> <span class="n">HelmholtzCoils</span><span class="o">::</span><span class="n">awg_recommendation</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">wire_gauges</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">10</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">22</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">31</span><span class="p">,</span><span class="mi">32</span><span class="p">,</span><span class="mi">34</span><span class="p">,</span><span class="mi">37</span><span class="p">,</span><span class="mi">40</span><span class="p">};</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">currentrecs_awg</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">15</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mf">2.5</span><span class="p">,</span><span class="mf">1.5</span><span class="p">,</span><span class="mf">1.0</span><span class="p">,</span><span class="mf">0.75</span><span class="p">,</span><span class="mf">0.5</span><span class="p">,</span><span class="mf">0.25</span><span class="p">,</span><span class="mf">0.125</span><span class="p">,</span><span class="mf">0.100</span><span class="p">,</span><span class="mf">0.075</span><span class="p">,</span><span class="mf">0.050</span><span class="p">,</span><span class="mf">0.025</span><span class="p">,</span><span class="mf">0.0125</span><span class="p">};</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">delta</span> <span class="o">=</span> <span class="n">DBL_MAX</span><span class="p">;</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">epsilon</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">awg_rec</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span><span class="p">(</span><span class="n">I</span><span class="o">&gt;=</span><span class="mf">0.0125</span> <span class="o">&amp;&amp;</span> <span class="n">I</span><span class="o">&lt;=</span><span class="mi">15</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">iter</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">iter</span><span class="o">&lt;</span><span class="mi">16</span><span class="p">;</span><span class="n">iter</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">epsilon</span> <span class="o">=</span> <span class="n">currentrecs_awg</span><span class="p">[</span><span class="n">iter</span><span class="p">]</span> <span class="o">-</span> <span class="n">I</span><span class="p">;</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span><span class="p">(</span><span class="n">epsilon</span><span class="o">&gt;=</span><span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">epsilon</span><span class="o">&lt;</span><span class="n">delta</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">delta</span> <span class="o">=</span> <span class="n">epsilon</span><span class="p">;</span></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">awg_rec</span> <span class="o">=</span> <span class="n">wire_gauges</span><span class="p">[</span><span class="n">iter</span><span class="p">];</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">awg_rec</span><span class="p">;</span></div><div class='line' id='LC41'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1162649/ad0df4769d545a40119ae40ee1267d069f0e3408/hhcoils.cxx" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1162649#file_hhcoils.cxx" style="float:right;margin-right:10px;color:#666">hhcoils.cxx</a>
            <a href="https://gist.github.com/1162649">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cm">/* HelmholtzCoils - demonstrating separation of analysis and toolkit interface in NDIToolbox by creating a</span></div><div class='line' id='LC2'><span class="cm">simple magnetic field calculator</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="cm">Chris Coughlin (TRI/Austin, Inc.)</span></div><div class='line' id='LC5'><span class="cm">*/</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="cp">#ifndef HELMHOLTZCOILS_H_</span></div><div class='line' id='LC8'><span class="cp">#define HELMHOLTZCOILS_H_</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'><span class="cp">#define _USE_MATH_DEFINES </span><span class="c1">// Required on some platforms to get mathematical constants</span></div><div class='line' id='LC11'><span class="cp">#include &lt;cmath&gt;</span></div><div class='line' id='LC12'><span class="cp">#include &lt;cfloat&gt;</span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'><span class="k">static</span> <span class="k">const</span> <span class="kt">double</span> <span class="n">mu_0</span> <span class="o">=</span> <span class="mi">4</span><span class="o">*</span><span class="n">M_PI</span><span class="o">*</span><span class="mf">1e-7</span><span class="p">;</span></div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'><span class="k">class</span> <span class="nc">HelmholtzCoils</span> <span class="p">{</span></div><div class='line' id='LC17'><span class="k">public</span><span class="o">:</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">HelmholtzCoils</span><span class="p">(</span><span class="kt">int</span> <span class="n">turns_per_coil</span><span class="p">,</span> <span class="kt">double</span> <span class="n">current_per_coil</span><span class="p">,</span> <span class="kt">double</span> <span class="n">coil_radius</span><span class="p">)</span><span class="o">:</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">N</span><span class="p">(</span><span class="n">turns_per_coil</span><span class="p">),</span> <span class="n">I</span><span class="p">(</span><span class="n">current_per_coil</span><span class="p">),</span> <span class="n">a</span><span class="p">(</span><span class="n">coil_radius</span><span class="p">),</span> <span class="n">lhcoil_position</span><span class="p">(</span><span class="o">-</span><span class="n">a</span><span class="o">/</span><span class="mi">2</span><span class="p">),</span> <span class="n">rhcoil_position</span><span class="p">(</span><span class="n">a</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">H</span><span class="p">(</span><span class="k">const</span> <span class="kt">double</span> <span class="n">position</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// Magnetic field at position (m) in A/m</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">centerH</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">H</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="p">}</span> <span class="c1">// Magnetic field at dead center of coils</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">B</span><span class="p">(</span><span class="k">const</span> <span class="kt">double</span> <span class="n">position</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">mu_0</span><span class="o">*</span><span class="n">H</span><span class="p">(</span><span class="n">position</span><span class="p">)</span><span class="o">*</span><span class="mi">1000</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// Flux density at position (m) in mT</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">centerB</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">B</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="p">}</span> <span class="c1">// Flux density at dead center of coils</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">B_mG</span><span class="p">(</span><span class="k">const</span> <span class="kt">double</span> <span class="n">position</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">B</span><span class="p">(</span><span class="n">position</span><span class="p">)</span> <span class="o">*</span> <span class="mf">1e4</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// Flux density at position (m) in mG</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">wirelength</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// Length of wire (m) to make N turns of radius a</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">awg_recommendation</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// Lookup table to make AWG recommendations based on current I</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC30'><span class="k">private</span><span class="o">:</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">int</span> <span class="n">N</span><span class="p">;</span> <span class="c1">// Turns per coil</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">I</span><span class="p">;</span> <span class="c1">// Current (A) per coil</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">a</span><span class="p">;</span> <span class="c1">// Common radius (m) of coils</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">lhcoil_position</span><span class="p">;</span> <span class="c1">// Position of left coil (m), defined as -a/2</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kt">double</span> <span class="n">rhcoil_position</span><span class="p">;</span> <span class="c1">// Position of right coil (m), defined as a/2</span></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// Geometry correction for magnetic field calcs</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">const</span> <span class="kt">double</span> <span class="n">geometry_correction</span><span class="p">(</span><span class="k">const</span> <span class="kt">double</span> <span class="n">coil_position</span><span class="p">,</span> <span class="k">const</span> <span class="kt">double</span> <span class="n">position</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> </div><div class='line' id='LC38'><span class="p">};</span></div><div class='line' id='LC39'><br/></div><div class='line' id='LC40'><span class="cp">#endif </span><span class="c1">// HELMHOLTZCOILS_H_</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1162649/5da12b6bc6b8d3327b9ff15158cc8cdecf761833/hhcoils.h" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1162649#file_hhcoils.h" style="float:right;margin-right:10px;color:#666">hhcoils.h</a>
            <a href="https://gist.github.com/1162649">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>%module hhcoils</div><div class='line' id='LC2'>%{</div><div class='line' id='LC3'>/* Includes the header in the wrapper code */</div><div class='line' id='LC4'>#include &quot;hhcoils.h&quot;</div><div class='line' id='LC5'>%}</div><div class='line' id='LC6'>/* Include various STL interfaces - not really needed here but included as a demo*/</div><div class='line' id='LC7'>%include &quot;std_string.i&quot;</div><div class='line' id='LC8'>%include &quot;std_vector.i&quot;</div><div class='line' id='LC9'>/* For vectors it&#39;s necessary to specify what type of vector(s) you&#39;ll be using-here we&#39;re</div><div class='line' id='LC10'>using the Python &quot;vector_float&quot; as an alias for vector&lt;float&gt;*/</div><div class='line' id='LC11'>namespace std {</div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;%template(vector_float) vector&lt;float&gt;;</div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;%template(vector_vector_float) vector&lt;std::vector&lt;float&gt; &gt;;</div><div class='line' id='LC14'>};</div><div class='line' id='LC15'><br/></div><div class='line' id='LC16'>/* Parse the header file to generate wrappers */</div><div class='line' id='LC17'>%include &quot;hhcoils.h&quot; </div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1162649/2d00f78aaaab3d51b15b11b97a5ffbc74f4d0f45/hhcoils.i" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1162649#file_hhcoils.i" style="float:right;margin-right:10px;color:#666">hhcoils.i</a>
            <a href="https://gist.github.com/1162649">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>SWIG’s role in our engine swap is to compile the C++ code into a library, and then to create new Python code as a wrapper. Our engine code is simple enough that we don’t require much in the way of configuration, but the config file adds handlers for strings and vectors just to illustrate their use.</p>
<p>To create the library depends on your C++ compiler and your operating system, what version of Python you&#8217;re using, etc. but essentially it entails running SWIG on your configuration file, compiling your C++ code and the wrapper code SWIG generates, and finally linking the compiled code into a static library (.so on Linux, .lib on Windows, etc.). For example, running SWIG with GCC on Linux on our toolkit engine:</p>
<pre>swig -c++ -python hhcoils.i
c++ -fpic -c hhcoils.cxx hhcoils_wrap.cxx -I /usr/include/python2.7/ -lstdc++
c++ -shared hhcoils_wrap.o hhcoils.o -o _hhcoils.so</pre>
<p>This creates a new Python wrapper hhcoils.py; this file and the _hhcoils.so static library is the new C++ Helmholtz coils calculation engine. We can then copy these two files to our pre-existing structure (overwriting our previous Python-only hhcoils.py engine), and the engine upgrade is complete. Our toolkit interface is unchanged and loads our GUI; our GUI already points to hhcoils.py and since we kept the same method names and signatures we don’t have to change the GUI either:</p>
<pre>#!/usr/bin/env python
import hhcoils

if __name__ == "__main__":
    coils = hhcoils.HelmholtzCoils(100, 0.6, 0.8382)
    print("Field at centre (A/m) = {0}".format(coils.centerH()))
    print("Recommend {0} metres of {1} AWG wire.".format(coils.wirelength(),
        coils.awg_recommendation()))</pre>
<h2>Wrapping Up</h2>
<p>The nice thing about using this approach to develop our application is we can get the best of both worlds. Python is generally a more productive programming language than C++, which means that we get our product out to the end user faster by developing in Python. If we find later on that we need a little speed boost, we can swap out the slow bits with a little C++ (or another language of your choosing) with little or no trouble.</p>
<p>There are many other ways you can speed up your Python application-the <a title="C-Extensions For Python" href="http://cython.org/">Cython</a> project takes a lot of the heavy lifting out of writing C extensions; <a title="PyPy JIT Compiler" href="http://pypy.org/">PyPy</a> uses a <a title="Just In Time (JIT) Compilation" href="http://en.wikipedia.org/wiki/Just-in-time_compilation">JIT</a> compiler to speed up your code, and so on.  Generally speaking if you&#8217;re worried about performance you should first make sure your Python code is as efficient as you can make it before you start thinking about these other options, but it&#8217;s nice to know they&#8217;re there if you need &#8216;em.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chriscoughlin.com/2011/08/swig-and-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AA&amp;S 2011 Presentation Available</title>
		<link>http://www.chriscoughlin.com/2011/08/aas-2011-presentation-available/</link>
		<comments>http://www.chriscoughlin.com/2011/08/aas-2011-presentation-available/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 18:22:23 +0000</pubDate>
		<dc:creator>crc</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[NDE]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[science]]></category>

		<guid isPermaLink="false">http://www.chriscoughlin.com/?p=110</guid>
		<description><![CDATA[I hadn&#8217;t noticed until now but Dave Forsyth&#8217;s presentation at the 2011 Aircraft Airworthiness &#38; Sustainment (AA&#38;S) Conference is available (mirrored here).  Dave was kind enough to add me to the list of authors; I don&#8217;t do much in the way &#8230; <a href="http://www.chriscoughlin.com/2011/08/aas-2011-presentation-available/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I hadn&#8217;t noticed until now but <a title="AA&amp;S 2011 Agenda" href="http://www.meetingdata.utcdayton.com/agenda/Agenda.asp?ID=airworthiness201101038448">Dave Forsyth&#8217;s presentation</a> at the <a title="AA&amp;S 2011 Conference Site" href="http://www.airworthiness2011.com/">2011 Aircraft Airworthiness &amp; Sustainment (AA&amp;S) Conference</a> is available (<a title="2011 AA&amp;S MAPOD Presentation" href="http://www.chriscoughlin.com/wp-content/uploads/2011/08/Progress-In-MAPOD-AAS-2011.pdf">mirrored here</a>).  Dave was kind enough to add me to the list of authors; I don&#8217;t do much in the way of Probability Of Detection (POD) but I did do the Python front-end that runs the models (originally written in <a title="R Project" href="http://www.r-project.org/">R</a>).</p>
<p>Developing the front end (PODToolkit) was interesting for me in that in was one of the first times I&#8217;ve really gone through a formal mock-up process.  Ordinarily I&#8217;ll sketch a few ideas for the user interface on paper or on the whiteboard, but this time around I needed to make sure that my ideas matched pretty closely with the end user&#8217;s.  After a few phone calls, emails, and one big fax we ended up at this for our mock-up:</p>
<p><a href="http://www.chriscoughlin.com/wp-content/uploads/2011/08/POD-Toolkit-Mockup.png"><img class="aligncenter size-medium wp-image-108" title="POD Toolkit Mockup" src="http://www.chriscoughlin.com/wp-content/uploads/2011/08/POD-Toolkit-Mockup-300x234.png" alt="" width="300" height="234" /></a></p>
<p>Which after a while ended up looking like this:</p>
<p><a href="http://www.chriscoughlin.com/wp-content/uploads/2011/08/POD-Toolkit-XP.png"><img class="aligncenter size-medium wp-image-109" title="POD Toolkit XP" src="http://www.chriscoughlin.com/wp-content/uploads/2011/08/POD-Toolkit-XP-300x225.png" alt="" width="300" height="225" /></a></p>
<p>All in all, I&#8217;m pretty pleased with how it turned out.  There&#8217;s a lot of information that has to be presented when you&#8217;re working with POD in Nondestructive Evaluation (NDE) and I like to think we did a good job of putting it together.  Hopefully we&#8217;ll get the chance to do some more work on it in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chriscoughlin.com/2011/08/aas-2011-presentation-available/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Transition Complete</title>
		<link>http://www.chriscoughlin.com/2011/08/transition-complete/</link>
		<comments>http://www.chriscoughlin.com/2011/08/transition-complete/#comments</comments>
		<pubDate>Sat, 13 Aug 2011 21:34:11 +0000</pubDate>
		<dc:creator>crc</dc:creator>
				<category><![CDATA[news]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://www.chriscoughlin.com/?p=49</guid>
		<description><![CDATA[Finally completed the move from a hand-rolled PHP template I wrote a long time ago to something more than a little easier to use. Whenever I had anything to put up on the site it used to feel like an &#8230; <a href="http://www.chriscoughlin.com/2011/08/transition-complete/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Finally completed the move from a hand-rolled PHP template I wrote a long time ago to something more than a little easier to use.  Whenever I had anything to put up on the site it used to feel like an all-day affair sometimes, having to update all those files by hand.  I doubt I&#8217;ll miss that.</p>
<p>I&#8217;ve taken down the older content &#8211; if there&#8217;s something from the old site that you want or desperately need let me know and I&#8217;ll get it going again.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chriscoughlin.com/2011/08/transition-complete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

