Jed Ludlowhttps://www.jedludlow.com/2020-10-10T13:00:00-06:00Multidisciplinary EngineerIn Search of Models that Yield Insight2020-10-10T13:00:00-06:002020-10-10T13:00:00-06:00Jed Ludlowtag:www.jedludlow.com,2020-10-10:/2020/10/in-search-of-models-that-yield-insight.html<p><em>"The purpose of computing is insight, not numbers." (Richard Hamming)</em></p>
<p><em>"The reason we model and analyze systems is to gain insight." <a href="https://books.google.com/books/about/Understanding_dynamic_systems.html?id=wnxRAAAAMAAJ">(C. Nelson Dorny)</a></em></p>
<p>At the beginning of April, with the COVID-19 outbreak upending much of life
as we previously knew it, I was casually following the case count numbers …</p><p><em>"The purpose of computing is insight, not numbers." (Richard Hamming)</em></p>
<p><em>"The reason we model and analyze systems is to gain insight." <a href="https://books.google.com/books/about/Understanding_dynamic_systems.html?id=wnxRAAAAMAAJ">(C. Nelson Dorny)</a></em></p>
<p>At the beginning of April, with the COVID-19 outbreak upending much of life
as we previously knew it, I was casually following the case count numbers
from various sources. I eventually gave in to the urge to start tinkering
with visualizations and started plotting the data from my home state of Utah. I originally
took inspiration from <a href="https://hairysun.com/">Matt Harrison's</a> daily <a href="https://www.linkedin.com/posts/panela_covid19-testkits-actlocal-activity-6651667546774867968-L7Lq">plots of
the data on LinkedIn</a>, but I ultimately ended up taking a different route to the visualizations
that was geared toward examining the commonality in the shape of the growth curves
and the phase relationships
between the various reported
statistics. I've since been updating the plots daily and
<a href="https://github.com/jedludlow/covid-19">storing the snapshots to GitHub</a>. An example snapshot from a typical day is below.</p>
<p><hr>
<img src="https://www.jedludlow.com/images/covid_multiple_y_axes.png" width="600" />
<br>
<em>Utah COVID-19 data. <a href="https://github.com/jedludlow/covid-19">(Source)</a></em>
<hr>
<img src="https://www.jedludlow.com/images/covid_multiple_log_y_axes.png" width="600" />
<br>
<em>Utah COVID-19 data, log scale. <a href="https://github.com/jedludlow/covid-19">(Source)</a></em>
<hr>
<img src="https://www.jedludlow.com/images/covid_daily_increments_multiple_y_axes.png" width="600" />
<br>
<em>Utah COVID-19 data, seven-day running average of daily case increments. <a href="https://github.com/jedludlow/covid-19">(Source)</a></em>
<hr></p>
<p>While the underlying case count data are admittedly an approximate proxy
for the true state of the pandemic, the plots offer at least some insights into
the progression over time. The plot with linear y axis is remarkable in demonstrating
how closely the various metrics track each other in terms of shape. The plot with logarithmic
y axis is useful for monitoring the effective exponential growth rate over time.
On a logarithmic y axis, exponential growth at a fixed rate would show up
as a straight line. The very steep apparent growth in late March slowed significantly
during April, and the data for the end of May and through June
looks pretty linear (on the log scale plot),
indicating relatively consistent exponential growth now
albeit at a much reduced rate than March. September shows strong growth again.
The seven-day moving average of daily totals is admittedly busy, but the phase
relationship between the various statistics is much easier to see this way.
The inclusion of public health directives
helps provide some context to changes in the shapes of the curves.</p>
<p>After working the visualization problem for a few days, I began to wonder about
how others were building models using this data to develop projections. Surely
that kind of information would be super helpful for public health officials. That's where
things got really interesting.</p>
<h2>"No Confidence" in the Confidence Bounds</h2>
<p>I've been following <a href="https://statmodeling.stat.columbia.edu/">Andrew Gelman's blog</a> for a handful of years now.
It acts as a unique collection point for a variety of interesting statistical questions,
and, even if I don't always fully appreciate the technicalities of some of the arguments,
the general exposure to the way Bayesian statisticians think about problems
has been educational. In the middle part of April, there was a discussion that
came up around two modeling groups that were publishing COVID-19 projections
with <a href="https://statmodeling.stat.columbia.edu/2020/04/21/new-coronavirus-forecasting-model/">wildly different shapes to the confidence bounds</a>.
I've reproduced a couple of the plots below.</p>
<p><hr>
<img src="https://www.jedludlow.com/images/covid_deaths_per_day_u_of_t.png" width="500" />
<br>
<em><a href="https://covid-19.tacc.utexas.edu/projections/">University of Texas COVID-19</a> projected deaths per day.
Note the quickly diverging confidence bounds. <a href="https://statmodeling.stat.columbia.edu/2020/04/21/new-coronavirus-forecasting-model/">(Source)</a></em>
<hr>
<img src="https://www.jedludlow.com/images/covid_deaths_per_day_imhe.png" width="500" />
<br>
<em><a href="https://covid19.healthdata.org/united-states-of-america">IHME COVID-19</a> projected deaths per day.
Note the quickly converging confidence bounds. <a href="https://statmodeling.stat.columbia.edu/2020/04/21/new-coronavirus-forecasting-model/">(Source)</a></em>
<hr></p>
<p>If you can take any insight from these models it might be that
projections from these types of models, especially so early in the progression
of a pandemic, are incredibly uncertain. They depend heavily on assumptions
about how previous pandemics have behaved, and there is no simple way to validate
those assumptions with an unfamiliar disease in our modern societal context.</p>
<p>As far as facilitating informed decision making, the hope that
statistical models like these might produce useful guidance seems dim. In that
light, is there another type of model that might serve us better? From a
policymaker's perspective, a pandemic like this gets managed day-to-day
on little bits of new information, and decisions are executed with some
risk that we are simply doing the wrong thing today which we won't discover
until some later date. From that description, it might be more suitable to think
about this as a
problem in learning how to control a system with uncertain dynamics.</p>
<h2>Controlling Systems with Uncertain Dynamics</h2>
<p>I remember reading David McCullough's <a href="https://www.simonandschuster.com/books/The-Wright-Brothers/David-McCullough/9781476728759">biography of the Wright brothers</a>,
which is loaded with insights into the genius of the two brothers.
They were absolutely convinced
that a critical piece of success in achieving flight would be to
<em>learn how to fly an aircraft</em>. Engineering a machine that was capable of flight
would not be enough because keeping such a machine aloft would require its own set
of skills. Wilbur Wright once compared the process to that of learning to
ride a horse. He contrasted two methods:</p>
<blockquote>
<p>One is to get on him and learn by actual practice how each motion and trick may be best met;
the other is to sit on a fence and watch the beast a while, and then retire to the house
and at leisure figure out the best way of overcoming his jumps and kicks. The latter system
is the safest, but the former, on the whole, turns out the larger proportion of good riders.</p>
</blockquote>
<p>Coming back to flying, he emphasized the need for practical experience behind the controls.</p>
<blockquote>
<p>But if you really wish to learn, you must mount a machine and become acquainted with its tricks by actual trial.</p>
</blockquote>
<p>There would be no substitute
for getting behind the controls and coming to grips with the reality that at first you don't
know how much to move the levers at your disposal, how much was too much, how much was too little.
The brothers together came up with a series of progressively more complex demonstration activities
that allowed them to <em>learn the dynamics of an unfamiliar aircraft system</em> and <em>develop the appropriate control reactions</em> to keep it aloft.</p>
<p>In a pandemic, what are the controls available to us? Mask mandates, gathering
restrictions, border shut-downs, stay-at-home orders, and quarantine periods
are typical examples, each with some impact on both public health and economic
outputs, the magnitude of which will not be well understood at first. In the
face of this uncertainty, one strategy is to establish a safe steady-state
operating point and then issue small changes on these control inputs to
observe the system outputs in response. We've all experienced this first hand
over the last several months, beginning with strict lock-downs to establish a
safe operating point from a public health perspective followed by progressive
re-opening plans and miscellaneous tweaking of restrictions and mandates in an
attempt to restore economic progress.</p>
<p>In principle, this strategy seems so straightforward. In practice, it
is incredibly difficult to execute well because the system we are dealing
with in a pandemic has dynamics which are especially challenging to our human
psychology. We are impatient. We don't like to wait. Furthermore, we expect
our control actions to make a noticeable effect on outputs in a relatively
short time window. In short, we are really bad at dealing with delay.</p>
<h2>Feedback Systems with Time Delay</h2>
<p>An exposure to the virus today will not yield a lab test result until many days later,
and there are multiple points of delay in that chain of events. Exposure to symptoms,
symptoms to lab test, lab test to results—these all accumulate into a very large delay
between infection and detection. This delay has enormous practical consequences on
our ability to exert control by feedback mechanisms.</p>
<p>Without delving deeply into control system theory, I'll simply state
that <em>delay pushes
feedback systems toward instability</em>. It causes systems with feedback loops
to overshoot and oscillate around their desired targets.</p>
<p>A simple example from thermal systems illustrates the significant human weakness
at dealing with slowly varying systems with built in delay. A
classic experiment from Dörner's <a href="https://lccn.loc.gov/96010986">The Logic of Failure</a> demonstrates this.
The experiment involves human participants interacting with a simulated
refrigeration system. He describes the premise of the experiment this way:</p>
<blockquote>
<p>Imagine that you are the manager of a supermarket. One evening the janitor
calls you up and tells you that the refrigeration system in the storeroom
for diary products appears to have broken down. Large quantities of milk
and milk products are in danger of spoiling. You rush to the store, where
the janitor tells you he has already contacted company headquarters. They
have dispatched refrigerator trucks to pick up the perishable goods, but
it will take several hours for the trucks to arrive. Until they do, the
perishables have to be kept from spoiling.</p>
<p>You find that the defective refrigeration system is equipped with a
regulator and a thermometer. The regulator is still operational and can
be used to influence the climate-control system and thus the temperature
in the storeroom. However, the numbers on the regulator do not correspond
to those on the thermometer. In general, a high regulator setting means
a high temperature; a low setting, a low temperature. But you do not know
what the exact relationship is between the regulator and the cooling system,
and you have to find out what it is. The regulator has a range of settings
between 0 and 200.</p>
</blockquote>
<p>Participants were told to adjust the regulator setting to target a stable
temperature of 4 degrees Celsius in the storeroom. Like real refrigeration
systems, this simulated system had significant time lag between the moment
that the regulator setting was changed and the time at which
resulting temperature changes became apparent.</p>
<p>The plots below are
a sampling of the performance from four participants. I won't attempt to
review all of the implications here, but it's worth noting the enormous
difference in performance between the very successful top participant and
the completely erratic bottom participant. Dörner's analysis
of the psychology at play in the various participants is worth reading, so
consult the book for a full discussion.
Of particular note is how the top performer made <em>only small adjustments
to the regulator setting at each change and them waited for quite some
time to allow the system to respond before making new adjustments</em>.
Eventually the oscillations died out, and a relatively steady downward
ramp toward the target resulted. In contrast,
the bottom performer demonstrated rapid adjustments to the regulator, going
from extreme to extreme or even reissuing the same extreme command multiple
times. The result was sustained oscillations, never converging on the target.</p>
<p><hr>
<img src="https://www.jedludlow.com/images/cold_storeroom_plots.jpg" width="500" />
<br>
<em>Plot of various participants' performance on the refrigerated storage room
simulation experiment, from <a href="https://lccn.loc.gov/96010986">The Logic of Failure</a>, p. 132. Solid lines
represent storage room temperature readings (degrees C). Triangles represent
regulator settings issued by the participants (unspecified units). The x axis
is time (minutes).</em>
<hr></p>
<h2>Conclusions</h2>
<p>From a policymaker's perspective, it feels like statistical models that attempt
to project long-term pandemic trajectories are less helpful
for managing the day-to-day decision making that must occur. It seems like
more insight comes from thinking
about a pandemic as an uncertain dynamic system, an unfamiliar aircraft that
is <em>already in flight</em>, a malfunctioning refrigeration system that <em>must remain
in operation</em>.</p>
<p>Pandemics have inherent delay in their dynamics, which complicates the system
identification problem.
To adequately learn the dynamics of a system with delay takes a <em>long</em> time because
you have to make <em>small control changes</em> and then <em>wait a long time</em> for the
oscillations to settle before making conclusions about the output. If
you get impatient and make control perturbations that are too large you create disturbances
that take a long time to settle out, you never really learn anything, and you
risk destabilizing the system entirely.</p>
<p>As Dörner showed us, some humans are particularly adept at controlling systems
with delay, and others are uniquely bad at it. I guess we can only hope
that during a pandemic a handful of the adept are in positions that
influence public health and economic policy.</p>Utah Code Camp 20152015-03-14T12:15:00-06:002015-03-14T12:15:00-06:00Jed Ludlowtag:www.jedludlow.com,2015-03-14:/2015/03/ucc-2015.html<p>I presented at Utah Code Camp 2015 on machine learning
with the Google Prediction API. IPython notebooks
are <a href="https://github.com/jedludlow/utah-code-camp-2015">available on GitHub</a>, or they can be viewed directly
with the IPython Notebook Viewer here:</p>
<ul>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/convert_input_files.ipynb">Converting Raw Input Files</a></li>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/ml_with_goog_pred.ipynb">Machine Learning with Google Prediction API</a></li>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/sklearn_fft_ave.ipynb">Taylor Swift Prediction with scikit-learn</a></li>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/google_prediction_fft_ave.ipynb">Taylor Swift …</a></li></ul><p>I presented at Utah Code Camp 2015 on machine learning
with the Google Prediction API. IPython notebooks
are <a href="https://github.com/jedludlow/utah-code-camp-2015">available on GitHub</a>, or they can be viewed directly
with the IPython Notebook Viewer here:</p>
<ul>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/convert_input_files.ipynb">Converting Raw Input Files</a></li>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/ml_with_goog_pred.ipynb">Machine Learning with Google Prediction API</a></li>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/sklearn_fft_ave.ipynb">Taylor Swift Prediction with scikit-learn</a></li>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/google_prediction_fft_ave.ipynb">Taylor Swift Prediction with Google Prediction API</a></li>
<li><a href="http://nbviewer.ipython.org/github/jedludlow/utah-code-camp-2015/blob/master/ipython_fft_example.ipynb">Interpreting NumPy FFTs</a></li>
</ul>Big Data Utah at StartSLC 20152015-01-30T02:25:00-07:002015-01-30T02:25:00-07:00Jed Ludlowtag:www.jedludlow.com,2015-01-30:/2015/01/bdu-startslc-2015.html<p>I presented on machine learning and prediction
to the <a href="http://www.bigdatautah.org/">Big Data Utah</a> meetings as part
of <a href="https://startslc.com/">StartSLC</a> 2015. Check out the <a href="http://www.jedludlow.com/prediction-demystified/">the slides</a>!</p>Utah Data Competition 20142014-10-28T22:57:00-06:002014-10-28T22:57:00-06:00Jed Ludlowtag:www.jedludlow.com,2014-10-28:/2014/10/udc-2014.html<p>I competed in this year's edition of the <a href="http://www.utahdatacompetition.com/">Utah Data Competition</a>,
a local data science competition. The semiconductor yield prediction problem
seemed simple enough on the surface, but it ultimately proved to be quite
challenging. I attempted several modeling approaches but eventually
converged on two that received most of my …</p><p>I competed in this year's edition of the <a href="http://www.utahdatacompetition.com/">Utah Data Competition</a>,
a local data science competition. The semiconductor yield prediction problem
seemed simple enough on the surface, but it ultimately proved to be quite
challenging. I attempted several modeling approaches but eventually
converged on two that received most of my attention:
a modified ridge regression with special cost function, and an
approximate Kalman filter (my dynamic systems background creeping in!). An IPython notebook with code for both approaches
is <a href="https://github.com/jedludlow/udc-2014">available on Github</a> for download or can be <a href="http://nbviewer.ipython.org/github/jedludlow/udc-2014/blob/master/utah_data_competition_2014.ipynb">viewed directly
with nbviewer</a>. A shorter summary of the notebook is
available as <a href="http://www.jedludlow.com/udc-2014/">slides</a>, too.</p>Who Was Harold Black?2014-09-03T20:02:00-06:002014-09-03T20:02:00-06:00Jed Ludlowtag:www.jedludlow.com,2014-09-03:/2014/09/harold-black.html<p>A little over a hundred years ago, some bright people
thought it might be <em>really useful</em> for someone
in New York to talk to someone in San Fransisco <a href="http://en.wikipedia.org/wiki/First_transcontinental_telephone_call"><em>by telephone</em></a>.
They eventually succeeded in completing the first
voice test of the system in 1914, and the first "official"
transcontinental long …</p><p>A little over a hundred years ago, some bright people
thought it might be <em>really useful</em> for someone
in New York to talk to someone in San Fransisco <a href="http://en.wikipedia.org/wiki/First_transcontinental_telephone_call"><em>by telephone</em></a>.
They eventually succeeded in completing the first
voice test of the system in 1914, and the first "official"
transcontinental long distance phone call occurred in January
of 1915.
As is often the case, the first implementation of the system
was really a prototype that would only handle limited load.
The ultimate vision was a system that could handle thousands
of voice calls simultaneously. There were large technical hurdles
to clear to make that a reality.</p>
<p>One of the primary hurdles was amplification. If you want to
string a very long wire and put lots of phone calls down that same
wire, you have to place repeater amplifiers
at points along the line that can boost the
signal up without distorting it or adding noise to it.
The amplifier technology of 1920 was not up to the task.</p>
<p>In 1921 a young electrical engineer named Harold Black joined the
<a href="http://en.wikipedia.org/wiki/Western_Electric">Western Electric Company</a>, an arm of the <a href="http://en.wikipedia.org/wiki/Bell_System">Bell System</a>, eventually
to become part of <a href="http://en.wikipedia.org/wiki/Bell_Labs">Bell Labs</a> when it was formed in 1925.
Within several months of joining,
Harold had succeeded in arranging an assignment to work
on stabilizing and linearizing amplifiers to support the
development of a large-scale long distance phone system. It would
be several years before his work bore fruit.</p>
<p><img alt="Alt text" src="https://www.jedludlow.com/images/Harold_Stephen_Black.gif" title="Harold Stephen Black"><br>
<em>Harold Black. <a href="http://en.wikipedia.org/wiki/File:Harold_Stephen_Black.gif">(Source)</a></em></p>
<p>If you've studied dynamic systems or control engineering
the names of Nyquist and Bode, also <a href="http://en.wikipedia.org/wiki/Bell_Labs">Bell Labs</a> scientists in the
early 20th century,
are most certainly familiar. But Harold Black? You've probably never heard
of him. Yet his invention revolutionized the telecommunications industry and
had far-reaching consequences in other branches of engineering.
Its impact can hardly be overstated. </p>
<p>What Harold invented is called the <a href="http://en.wikipedia.org/wiki/Negative_feedback_amplifier"><em>negative feedback amplifier</em></a>.
This classic video footage on the subject from the AT&T archives is worth watching:</p>
<div class="youtube" align="left">
<iframe width="420" height="315" src="//www.youtube.com/embed/iFrxyJAtJ7U" frameborder="0" allowfullscreen></iframe>
</div>
<p>Aside: The hand sketches on newsprint shown in the video actually came five days
later and relate to impedance matching the amplifier to the load.
According to an <a href="http://dx.doi.org/10.1109/MSPEC.1977.6501721">article published in IEEE Spectrum</a>, the
sketches from the initial invention, also sketched on newsprint, were actually a simple block diagram and a couple of equations.</p>
<p><img src="https://www.jedludlow.com/images/negative_feedback.png" width="315" /><br>
<em>Negative feedback block diagram and equations. <a href="http://dx.doi.org/10.1109/MSPEC.1977.6501721">(Source)</a></em></p>
<p>For me personally, the invention itself is only part of the significance of this story. I'm
forever grateful for Harold's candor in describing his years
of unsuccessful design attempts and the flash of inspiration that ultimately
accompanied the final breakthrough.
This is <a href="http://dx.doi.org/10.1109/MSPEC.1977.6501721">his own written description</a> of the event:</p>
<blockquote>
<p>Then came the morning of Tuesday, August 2, 1927,
when the concept of the negative feedback amplifier came
to me in a flash while I was crossing the Hudson River on
the Lackawanna Ferry, on my way to work. For more than
50 years I have pondered how and why the idea came, and
I can't say any more today than I could that morning. All
I know is that after several years of hard work on the
problem, I suddenly realized that if I fed the amplifier
output back to the input, in reverse phase, and kept the
device from oscillating (singing, as we called it then), I
would have exactly what I wanted: a means of canceling
out the distortion in the output. I opened my morning
newspaper and on a page of <em>The New York Times</em> I
sketched a simple canonical diagram of a negative feedback
amplifier plus the equations for the amplification
with feedback. I signed the sketch, and 20 minutes
later, when I reached the laboratory at 463 West Street,
it was witnessed, understood, and signed by the late Earl
C. Blessing. </p>
</blockquote>
<p>With that, here is my
personal recipe for changing the world while remaining
in relative obscurity, modeled on the work of Harold Black:</p>
<blockquote>
<p>Pursue opportunities that have the potential of
making a serious difference in the world. Work on hard problems. When solutions
don't immediately present themselves, keep going. Wait
patiently for pure inspiration.</p>
</blockquote>
<p><em>(An <a href="http://www.ieeeghn.org/wiki/index.php/Oral-History:Harold_S._Black">extended oral history</a> of Harold Black's contributions is available
from the IEEE History Center.)</em></p>Getting IPython rmagic to Work on Windows2014-04-29T01:26:00-06:002014-04-29T01:26:00-06:00Jed Ludlowtag:www.jedludlow.com,2014-04-29:/2014/04/getting-ipython-rmagic-to-work-on.html<p>After updating to <a href="http://ipython.org/">IPython</a> 2.0, I decided to get <a href="http://ipython.org/ipython-doc/dev/config/extensions/rmagic.html"><code>rmagic</code></a> working
on a Windows 8.1 install. These instructions should probably work with
IPyhon 1.X, too, although I have not tried. </p>
<h2>R on Windows</h2>
<p>Behind the scenes, rmagic assumes that a working version of <a href="http://www.r-project.org/">R</a>
is available on …</p><p>After updating to <a href="http://ipython.org/">IPython</a> 2.0, I decided to get <a href="http://ipython.org/ipython-doc/dev/config/extensions/rmagic.html"><code>rmagic</code></a> working
on a Windows 8.1 install. These instructions should probably work with
IPyhon 1.X, too, although I have not tried. </p>
<h2>R on Windows</h2>
<p>Behind the scenes, rmagic assumes that a working version of <a href="http://www.r-project.org/">R</a>
is available on the Windows <code>PATH</code>. The most recent Windows
installers for R 3.0 do not modify the <code>PATH</code>
variable. This is actually a good thing because it allows you to install
multiple versions of R in whatever 32-bit or 64-bit flavors you'd like,
and they can all co-exist peacefully. That said, to get rmagic
to work you'll have to put one of
them on the <code>PATH</code> by hand.</p>
<h3>Which Flavor?</h3>
<p>The flavor of R you put on the <code>PATH</code> must
match the flavor of Python you are targeting. More specifically, if
you're running 32-bit Python, place a 32-bit flavor of R on the path.
The locations of these binaries will probably look something like this:</p>
<ul>
<li>32-bit R: <code>C:\Program Files\R\R-3.0.3\bin\i386</code></li>
<li>64-bit R: <code>C:\Program Files\R\R-3.0.3\bin\x64</code></li>
</ul>
<p>It's <em>critical</em> to go all the way down to these flavor-specific
directories since it's really <code>R.dll</code> that
needs be available to rmagic. Why
is that? Read on.</p>
<h3><code>rpy2</code></h3>
<p>In addition to a working R install, rmagic in
IPython 2.0 uses <a href="http://rpy.sourceforge.net/rpy2.html"><code>rpy2</code></a> as
the connection between Python and R. Installing <code>rpy2</code> on
Windows is not quite as simple as it perhaps should be, and <a href="http://stackoverflow.com/search?q=rpy2+windows">Stack
Overflow is littered</a> with questions about failed attempts at using <code>pip</code>
or <code>easy_install</code>.
After culling through several of those posts, I happened upon one that
actually had the <a href="http://stackoverflow.com/questions/5068760/bizzarre-issue-trying-to-make-rpy2-2-1-9-work-with-r-2-12-1-using-python-2-6-un">right magic beans</a>. The post is a little dated, so
here's a refreshed summary of the simplest path to success today:</p>
<ol>
<li>As described above, pick a suitable flavor of R, and put it on the
<code>PATH</code>.</li>
<li>Pull down the (unofficial) <a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/#rpy2"><code>rpy2</code> binaries</a> from
<a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/">Christhoph Gohlke's treasure trove</a>. Make sure you pick the right Python version of the
binaries to match your Python flavor, including Python version
number.</li>
<li>Install those binaries into whatever Python environment you intend
to use. (Did you know you can <a href="http://stackoverflow.com/questions/3271590/can-i-install-python-windows-packages-into-virtualenvs">install binary packages into any Python environment</a>, even those not in the Windows registry? That
includes an <a href="https://store.continuum.io/cshop/anaconda/">Anaconda</a> install.)</li>
<li>Create an environment variable called <code>R_HOME</code>,
and point it to the base R install directory. If your paths look
like those above, that would be <code>"C:\Program
Files\R\R-3.0.3"</code> or
whatever matches your R version.</li>
<li>Create an environment variable
called <code>R_USER</code>, and set it to your Windows username.
This looks to be in line with <a href="https://bitbucket.org/lgautier/rpy2/issue/95/automagic-settings-for-windows">recent discussion</a> on the R
development issues list.</li>
</ol>
<p>Once you've done all that, open up a fresh command prompt and verify
that all your environment changes were correctly set. Then fire up
IPython notebook, issue</p>
<div class="highlight"><pre><span></span><code><span class="nf">%load_ext</span> <span class="n">rmagic</span>
</code></pre></div>
<p>in a cell, and the rest of the
<a href="http://ipython.org/ipython-doc/dev/config/extensions/rmagic.html">guidance in the IPython documentation</a>
should then apply.</p>
<h2>Some Issues</h2>
<p>Unfortunately, it's not necessarily
all roses after that. There are still issues with getting some
information back and forth across the R-Python interface in pristine
format. Sometimes the output from R commands doesn't completely make it
into the notebook and ends up being printed in the command shell window
from which the notebook is running. But aside from a few minor
inconveniences, it doesn't look like there are any real errors
happening.</p>Irrigation System Performance Measurement on the Cheap2014-04-26T11:33:00-06:002014-04-26T11:33:00-06:00Jed Ludlowtag:www.jedludlow.com,2014-04-26:/2014/04/irrigation-system-performance.html<p>What began as a simple exercise in turning on the irrigation water to
the yard culminated in an hour of <a href="http://sethgodin.typepad.com/seths_blog/2005/03/dont_shave_that.html">yak shaving</a> in which I actually
measured the performance of my sprinklers. The well-meaning people at my
City Hall had sent out an informative flyer earlier in the week with …</p><p>What began as a simple exercise in turning on the irrigation water to
the yard culminated in an hour of <a href="http://sethgodin.typepad.com/seths_blog/2005/03/dont_shave_that.html">yak shaving</a> in which I actually
measured the performance of my sprinklers. The well-meaning people at my
City Hall had sent out an informative flyer earlier in the week with
tips about conserving water during the upcoming summer, not recognizing
the Siren song they would ultimately create for me by suggesting that
one could <em>measure</em> and <em>optimize</em> a sprinkler system. While my
engineering disease puts me at risk for over optimization to start with,
I'm particularly susceptible to the temptation posed by measurement
science problems.</p>
<p>The flyer included a link to a web address with detailed
instructions for <a href="http://wateringschedule.com/">computing station timing</a> for a yard irrigation
system, sponsored by <a href="http://www.orbitonline.com/">Orbit Irrigation</a>. I wasn't about to pay for
<a href="http://www.amazon.com/gp/product/B00CBZB8U8">the catch cup kit</a> they were offering, but fortunately they gave away
the key specification for supplanting the commercial catch cups with
something ad hoc. Off I went looking for something with a 16.25 square
inch catch opening. An opening diameter of about 4.6 inch does the
trick.</p>
<p>With some luck, it didn't take me long to find a reasonable
solution. Who knew that the cottage cheese industry was secretly out to
ruin the catch cup business for the irrigation industry? I no longer
question why my wife has saved so many of these in a drawer in the
kitchen. I now understand that they are a valuable instrument to an
irrigation system measurement technician, and she <em>must</em> have realized
that long before I did.</p>
<p><img src="https://www.jedludlow.com/images/cottage_cheese_cup.jpg" width="315" />
<img src="https://www.jedludlow.com/images/measure_cup_opening.jpg" width="300" /></p>
<p>With catch cups in hand, I headed to the yard to make
measurements. My yard has conventional pop up spray heads in the front
and a bit fancier gear driven rotor heads in the back. When I installed
the rotors a couple of years ago the hardware store people told me I'd
have to run them a lot longer than the old pop ups, but their even spray
pattern would provide better overall performance. Quite honestly, the
back lawn didn't fare very well over the last summer compared to the
front, so a primary goal of my measurements was to get a feel for just
how much longer the recommended station timing would be for the back
yard rotors.</p>
<p><img src="https://www.jedludlow.com/images/cups_on_grass.jpg" /></p>
<p>After laying out catch cups and throwing on the stations for
several minutes I was ready to measure the volume of water in each cup.
I debated using a tablespoon and converting the measurements to mL
later, but then I remembered that there is another stash of special
little plastic cups in our house has that has mL graduations built right
in. Thank you, children's cold medicine people, for providing miniature
graduated cylinders in every box!</p>
<p><img src="https://www.jedludlow.com/images/take_your_medicine.jpg" width="300"/></p>
<p>I decided to scale back the effort and only measure one station in the
front and one in the back. I found the simple instructions for mapping
and recording the measurements as suggested by the website to be quite
helpful. </p>
<p><img src="https://www.jedludlow.com/images/raw_sprinkler_notes.jpg" /></p>
<p>With final measurements in hand it was a simple matter to run the
calculator on the website. I won't post the final recommended run times
since they would be specific to my system, climate, and soil type. But I
will say that, much to my surprise, the gear rotors need to run <em>four
times</em> as long as the pop ups to deliver an equivalent volume of water
to the yard. That's a lot longer than I was running them last summer
when the back grass was looking so bad. And it only took me one
inexpensive yak shave to figure that out.</p>My 15 Seconds of Car Talk Fame2013-03-03T21:54:00-07:002013-03-03T21:54:00-07:00Jed Ludlowtag:www.jedludlow.com,2013-03-03:/2013/03/my-15-seconds-of-car-talk-fame.html<p>It was a dark day around our house several months ago when it was
announced that no new <a href="http://www.cartalk.com/">Car Talk</a> episodes would be recorded. The show
has been part of my week for nearly 20 years. Like all great shows that
are eventually put out to pasture, we can still …</p><p>It was a dark day around our house several months ago when it was
announced that no new <a href="http://www.cartalk.com/">Car Talk</a> episodes would be recorded. The show
has been part of my week for nearly 20 years. Like all great shows that
are eventually put out to pasture, we can still enjoy reruns. Much to my
surprise, <a href="http://www.cartalk.com/content/1309-pit-despair">this week's "best-of" show</a> contained <a href="https://docs.google.com/file/d/0B_IxcYvuiw0WVTlxWGZmZFo4cUE/edit?usp=sharing">my 15 seconds of Car
Talk fame</a>. </p>
<p>Shortly after starting graduate school, I was dutifully toiling away
on homework one Saturday morning with Car Talk playing in the
background. This was long before the podcast era, so if you didn't hear
it when it was originally broadcast you pretty much missed it for that
week. At any rate, a <a href="http://www.scouting.org/scoutsource/CubScouts.aspx">Cub Scout</a> Den Mother called in with some
questions about how to advise her Cubs on the issue of weight placement
in their Pinewood Derby cars. I wasn't completely satisfied with Tom and
Ray's answer, so I wrote up a quick technical note called <em><a href="https://docs.google.com/file/d/0B_IxcYvuiw0WTjdBbEJxV291UXM/edit?usp=sharing">On the
Placement of Weight in a Pinewood Derby Car</a> </em>and mailed it in, never
expecting to hear more of it. </p>
<p>Some weeks later I got a phone call from a relative, asking me if I had
ever sent anything in to the Car Talk guys. I confirmed that I had but
was puzzled as to why he would know about it. It turns out that my
write-up had been mentioned during a "Stump the Chumps" segment of the
show that week, and he called to tell me about it. I had missed the
broadcast entirely. This week's rebroadcast was actually the first time
I heard it for myself.</p>
<p><img style="float:right" src="https://www.jedludlow.com/images/A_Fast_Car.jpg" /></p>
<p>I still have my first Pinewood Derby car, the one that took first place
in my local race. It stays safely packed away in a box and only comes
out for special occasions. You can guess its age by the <a href="http://en.wikipedia.org/wiki/Pontiac_Firebird">Firebird</a>
logo on the front. Thanks to a great father and to other great Scout
leaders those were special days never to be forgotten.</p>
<p>Many years later now, it takes more than one hand's worth of fingers to
count the number of derbies I've participated in with my own sons. I can
say with fairly high confidence that, backed by empirical evidence,
weight placement is <em>not</em> the most important factor in the speed of a
car. Sure, you should still bring the car up to the maximum allowable
weight and place that weight near the rear axle to be a competitor. But
invariably the fastest cars have ultra low rolling resistance, and they
<em>track perfectly straight</em>. No amount of weight fiddling can compensate
for a car that incurs huge amounts of drag by continually rubbing up
against the central track guide.</p>A Quick FFT Example in Python2012-11-19T04:42:00-07:002012-11-19T04:42:00-07:00Jed Ludlowtag:www.jedludlow.com,2012-11-19:/2012/11/a-quick-fft-example-in-python.html<p>Here's a quick <a href="http://ipython.org/">IPython</a> notebook <a href="https://gist.github.com/3919130">gist</a> about FFTs in Python.
Ironically, most tutorials don't describe how to scale and format the
FFT output so that sinusoidal amplitudes are correctly displayed.
Sometimes that's important. If you don't have IPython installed, the
<a href="http://nbviewer.ipython.org/3919130">notebook can be viewed</a> using the awesome <a href="http://nbviewer.ipython.org/">IPython Notebook
Viewer …</a></p><p>Here's a quick <a href="http://ipython.org/">IPython</a> notebook <a href="https://gist.github.com/3919130">gist</a> about FFTs in Python.
Ironically, most tutorials don't describe how to scale and format the
FFT output so that sinusoidal amplitudes are correctly displayed.
Sometimes that's important. If you don't have IPython installed, the
<a href="http://nbviewer.ipython.org/3919130">notebook can be viewed</a> using the awesome <a href="http://nbviewer.ipython.org/">IPython Notebook
Viewer</a>.</p>A Find Rarer Than Diamonds2012-04-08T19:16:00-06:002012-04-08T19:16:00-06:00Jed Ludlowtag:www.jedludlow.com,2012-04-08:/2012/04/a-find-rarer-than-diamonds.html<p>So maybe <a href="http://tanzanitefoundation.org/tanzanite_rarity">diamonds aren't the rarest gemstone</a>, but I couldn't very
well title the post "A Find Rarer Than Tanzanite" and expect anyone to
understand the idiom.</p>
<p>I found a professional athlete who could actually serve as a role model
for youth! Check out <a href="http://www.deseretnews.com/article/765566532/AC-Green-is-an-iron-man-on-and-off-the-court.html?pg=all">this great article about A.C …</a></p><p>So maybe <a href="http://tanzanitefoundation.org/tanzanite_rarity">diamonds aren't the rarest gemstone</a>, but I couldn't very
well title the post "A Find Rarer Than Tanzanite" and expect anyone to
understand the idiom.</p>
<p>I found a professional athlete who could actually serve as a role model
for youth! Check out <a href="http://www.deseretnews.com/article/765566532/AC-Green-is-an-iron-man-on-and-off-the-court.html?pg=all">this great article about A.C. Green</a>, former
basketball star for the Lakers. I've re-posted just a few paragraphs. </p>
<blockquote>
<p>Former Los Angeles Lakers star A.C. Green became known as the NBA's
"Iron Man" for playing in a record 1,192 straight games. </p>
<p>Turns out he almost didn't play pro basketball at all. </p>
<p>While visiting a former teacher in Hermiston, Ore., with 10 of his
closest friends, the group decided to attend a nearby Christian
church. After the service, the pastor and Green discussed his
spiritual future and the prospect of being found in the Kingdom of
God. The 17-year-old high school all-American, who had just received a
full-ride scholarship to the number one basketball school in the
country — Oregon State — had only one question: "Does this mean I
don't play basketball anymore?" </p>
<p>Although he was willing to give up the game altogether, the pastor
told him that wouldn't be necessary, as long as he honored the Lord
through his game. However, Green's response showed the beginning of
his "all chips in" approach to the Christian lifestyle. </p>
<p>"There was no turning back for me," Green says. "Matthew 6:33: 'Seek
ye first the kingdom of God and all things shall be added unto you'
was just something I was dumb enough to believe was true. I told the
Lord 'You redefine what it is that I am now as a man. You tell me who
A.C. Green is. What people say and what you say are two different
things and I need to know what it is that you say.'"</p>
</blockquote>Exporting C++ Classes from a DLL2011-10-13T20:47:00-06:002011-10-13T20:47:00-06:00Jed Ludlowtag:www.jedludlow.com,2011-10-13:/2011/10/exporting-c-classes-from-dll.html<p>Two good articles on exporting C++ classes from a DLL from <a href="http://eli.thegreenplace.net/2011/09/16/exporting-c-classes-from-a-dll/">Eli
Bendersky</a> and <a href="http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx?fid=1525934&df=90&mpp=25&noise=3&prof=False&sort=Position&view=Quick&fr=26#CppMatureApproach">Alex Blekhman</a>. I've researched this before and
found varying degrees of intelligibility. These seem to be fairly
complete yet concise.</p>We All Better Start Drivin' Prii2011-08-02T19:19:00-06:002011-08-02T19:19:00-06:00Jed Ludlowtag:www.jedludlow.com,2011-08-02:/2011/08/we-all-better-start-drivin-prii.html<p>Thanks to this week's <a href="http://www.cartalk.com/content/1131-love-and-rust-spots">Car Talk</a> for this musical gem: "Sure as cactus
is cacti and fungus is fungi, we all better start drivin' <a href="http://en.wikipedia.org/wiki/Toyota_Prius">Prii</a>
...." </p>
<p>Download a short clip: <a href="https://drive.google.com/file/d/1ZETKWGD-XWZrvQwsf0oEKIKhscHLY_OO/view?usp=sharing">We All Better Start Drivin' Prii</a> </p>
<p>Toyota actually issued a <a href="http://pressroom.toyota.com/releases/toyota-announces-the-plural-of-prius.htm">press release</a>, officially proclaiming that
the public had selected the plural …</p><p>Thanks to this week's <a href="http://www.cartalk.com/content/1131-love-and-rust-spots">Car Talk</a> for this musical gem: "Sure as cactus
is cacti and fungus is fungi, we all better start drivin' <a href="http://en.wikipedia.org/wiki/Toyota_Prius">Prii</a>
...." </p>
<p>Download a short clip: <a href="https://drive.google.com/file/d/1ZETKWGD-XWZrvQwsf0oEKIKhscHLY_OO/view?usp=sharing">We All Better Start Drivin' Prii</a> </p>
<p>Toyota actually issued a <a href="http://pressroom.toyota.com/releases/toyota-announces-the-plural-of-prius.htm">press release</a>, officially proclaiming that
the public had selected the plural of Prius to be Prii. But I can't help
but wonder if the whole campaign got kicked off when one of the Toyota
marketing guys was watching <a href="http://en.wikiquote.org/wiki/Brian_Regan#From_Brian_Regan_Live:_Stupid_in_School_.5B1.5D">Brian Regan's Stupid in School</a> sketch
and thought to himself, "Hey, what if ...."</p>Bob Pease Killed in Car Crash2011-07-20T06:49:00-06:002011-07-20T06:49:00-06:00Jed Ludlowtag:www.jedludlow.com,2011-07-20:/2011/07/bob-pease-killed-in-car-crash.html<p><a href="http://edn.com/electronics-blogs/readerschoice/4368147/Analog-engineering-legend-Bob-Pease-killed-in-car-crash">Analog engineering legend Bob Pease killed in car crash</a> </p>
<p>As a university student I took a job in an <em>electronics</em> lab while
studying <em>mechanical</em> engineering. I guess the job required that you
could solder <em>and</em> do a little metalworking, so I qualified on the latter
and learned the former. In …</p><p><a href="http://edn.com/electronics-blogs/readerschoice/4368147/Analog-engineering-legend-Bob-Pease-killed-in-car-crash">Analog engineering legend Bob Pease killed in car crash</a> </p>
<p>As a university student I took a job in an <em>electronics</em> lab while
studying <em>mechanical</em> engineering. I guess the job required that you
could solder <em>and</em> do a little metalworking, so I qualified on the latter
and learned the former. In retrospect, it was the best possible thing I
could have done at the time. It completely cured my fear of electronics,
and it set the stage for a future filled with problems that didn't fit
into a single engineering discipline. </p>
<p>All the guys I worked with in the lab read Bob Pease every time he was
published. I started reading, too, even though I didn't always
understand what his circuits did. I do recall, however, being able to
grasp his articles on <a href="https://www.google.com/search?q=bob+pease+fuzzy+logic">fuzzy logic</a> as a student, mostly because I had
studied enough control systems to make the discussion relevant. At the
time, analog implementations for compensators were considered
yesterday's news by academia. Bob showed us that they were as relevant
as they ever were.</p>On Jean Labrosse's Coding Style2011-06-03T04:43:00-06:002011-06-03T04:43:00-06:00Jed Ludlowtag:www.jedludlow.com,2011-06-03:/2011/06/on-jean-labrosses-coding-style.html<blockquote>
<p><em>The words or the language, as they are written or spoken, do not seem
to play any role in my mechanism of thought. The psychical entities
which seem to serve as elements in thought are certain signs and more
or less clear images which can be 'voluntarily' reproduced and
combined …</em></p></blockquote><blockquote>
<p><em>The words or the language, as they are written or spoken, do not seem
to play any role in my mechanism of thought. The psychical entities
which seem to serve as elements in thought are certain signs and more
or less clear images which can be 'voluntarily' reproduced and
combined. .... This combinatory play seems to be the essential feature
in productive thought before there is any connection with logical
construction in words or other kinds of signs which can be
communicated to others.</em> (Albert Einstein in a letter to Jacques
Hadamard)</p>
</blockquote>
<p><a href="http://micrium.com/about/management/">Jean Labrosse</a>, the well-respected author of the <a href="http://micrium.com/page/products/rtos/os-ii">µC/OS-II RTOS</a>,
recently published an article in Embedded Systems Design entitled
<a href="http://www.embedded.com/design/prototyping-and-development/4215492/Adopting-C-programming-conventions">Adopting C programming conventions</a>. If you've read the article, you
can easily understand the stir it might create. Some of the ideas he
advocates are not generally accepted as "good practice" among most
embedded developers. It is no surprise that the comment section that
follows the article is full of gripes and is largely devoid of praise. </p>
<p>Ironically, the source code for µC/OS-II is cited by many as a prime
example of beautiful, clean embedded C code, worthy of study. The RTOS
itself is considered to be highly reliable. True to form, the coding
style throughout conforms to Mr. Labrosse's conventions. Quite a
paradox. </p>
<p>My first response was to conclude that maybe Mr. Labrosse is just
smarter than all the rest of us, and it wouldn't matter if his coding
style were in complete opposition to what most consider "good practice."
He'd figure out how to bring order to the system and ship something
exceptional. That may, in fact, be true. But then I remembered the above
from Einstein, and it completely changed my line of thought toward
something more productive. </p>
<p>Source code is such a crude description of the intricate mental models
that reside in our heads when crafting software systems. The process of
first distilling a mental model to code is so much smoother than the
process of recreating a mental model from reading source code.
Unfortunately, most of us lead lives that prevent us from maintaining
that system model in our heads indefinitely. We're constantly required
to rebuild the model after being away from the problem for a while. As I
look closer at Mr. Labrosse's conventions, I see a set of rules that
allow him to create a richer <em>reading</em> experience for himself, each
construct seeded with clues about how it fits into the larger system,
assisting him to reconstruct the "clear images" in his mind each time he
returns to the code. That sounds like "good practice" to me.</p>Wrapping C++ in a C Interface2011-01-22T14:49:00-07:002011-01-22T14:49:00-07:00Jed Ludlowtag:www.jedludlow.com,2011-01-22:/2011/01/this-is-perhaps-simplest-slickest-way.html<p>This is perhaps the simplest, slickest way to wrap C++ in a C interface
I've ever seen, <a href="http://matt.eifelle.com/2010/12/09/wrapping-a-c-class-in-c/">courtesy of Matthieu Brucher</a>. The key concept is the
forward declaration of the Manager type, which is valid for both C++ and
C. Any C that attaches to this interface doesn't have to …</p><p>This is perhaps the simplest, slickest way to wrap C++ in a C interface
I've ever seen, <a href="http://matt.eifelle.com/2010/12/09/wrapping-a-c-class-in-c/">courtesy of Matthieu Brucher</a>. The key concept is the
forward declaration of the Manager type, which is valid for both C++ and
C. Any C that attaches to this interface doesn't have to know that the
underlying Manager struct may actually look more like a C++ struct. It
just needs a valid pointer to Manager. No need to destroy type
information and worry about re-casting void pointers. </p>
<p>First the header file: </p>
<div class="highlight"><pre><span></span><code><span class="cp">#ifndef INTERFACE_H</span>
<span class="cp">#define INTERFACE_H</span>
<span class="cp">#ifdef __cplusplus</span>
<span class="k">extern</span> <span class="s">"C"</span>
<span class="p">{</span>
<span class="cp">#endif</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">Manager</span> <span class="n">Manager</span><span class="p">;</span>
<span class="n">Manager</span><span class="o">*</span> <span class="nf">create_manager</span><span class="p">();</span>
<span class="kt">void</span> <span class="nf">destroy_manager</span><span class="p">(</span><span class="n">Manager</span><span class="o">*</span> <span class="n">manager</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">print_manager</span><span class="p">(</span><span class="n">Manager</span><span class="o">*</span> <span class="n">manager</span><span class="p">);</span>
<span class="cp">#ifdef __cplusplus</span>
<span class="p">}</span>
<span class="cp">#endif</span>
<span class="cp">#endif</span>
</code></pre></div>
<p>And now the implementation: </p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span> <span class="cpf">"interface.h"</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">"manager.h"</span><span class="cp"></span>
<span class="n">Manager</span><span class="o">*</span> <span class="nf">create_manager</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">Manager</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">destroy_manager</span><span class="p">(</span><span class="n">Manager</span><span class="o">*</span> <span class="n">manager</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">delete</span> <span class="n">manager</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">print_manager</span><span class="p">(</span><span class="n">Manager</span><span class="o">*</span> <span class="n">manager</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">manager</span><span class="o">-></span><span class="n">print</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div>