<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Python for Power Systems]]></title>
  <link href="http://www.whit.com.au/blog/atom.xml" rel="self"/>
  <link href="http://www.whit.com.au/blog/"/>
  <updated>2013-03-24T10:13:35+11:00</updated>
  <id>http://www.whit.com.au/blog/</id>
  <author>
    <name><![CDATA[whit]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Keyword arguments for PSSE Functions]]></title>
    <link href="http://www.whit.com.au/blog/2012/12/keyword-arguments-for-psse-functions/"/>
    <updated>2012-12-31T12:21:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/12/keyword-arguments-for-psse-functions</id>
    <content type="html"><![CDATA[<p>Following on from the last video
&#8221;<a href="http://www.whit.com.au/blog/2012/12/solve-a-loadflow-with-psse/">How to solve a loadflow with Python</a>&#8221;</p>

<p>This video explains exactly how and why I used keyword arguments in my Python functions.
If you want to learn how to make your scripts easier to read, this 9 minute video is for you.</p>

<!--more-->


<div class="flash-video">
    <div>
        <iframe width="420" height="315" src="http://www.youtube.com/embed/JLwVk-1PpdQ?rel=0" frameborder="0" allowfullscreen></iframe>
    </div>
</div>


<p>If you want to see more tutorial posts like this: Tell us what topic you&#8217;d
like covered using <a href="#wufoo-m7x3w7">this form</a></p>

<h4>Transcript</h4>

<p>Hi there power system engineers, last video we talked about how to make a
full newton rapheson solution with Python and PSSE. And during that example I
showed how to use keyword arguments to your function. Inside my <code>fnsl</code>
function I&#8217;ve used <code>options1=0</code> and <code>options5=0</code> to turn off taps and switched
shunt adjustments.</p>

<h5>The old way</h5>

<p>You might be familiar with the alternate form of calling a function with the
<code>_i</code> in it. I&#8217;m going to show you how I wrote a function with <code>options1</code> and
<code>options5</code> keywords based on the documentation.</p>

<p>You might be more familiar with the <code>_i</code> arguments that PSSE provides. WHen you
record a macro into a Python file you might find something that looks like
this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">fnsl</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="n">_i</span><span class="p">,</span> <span class="n">_i</span><span class="p">,</span> <span class="n">_i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">_i</span><span class="p">,</span> <span class="n">_i</span><span class="p">])</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now this equivalent to the one above, <code>options1</code> is set to zero and <code>options5</code>
is set to zero. However then you need to fill in the intermediate options
with these default integers which PSSE takes to mean don&#8217;t set this option
leave it as the default. You&#8217;ll get something like this from the PSSE record
macro.</p>

<h5>Why change from the older method?</h5>

<p>What I do is I replace this list of integer arguments with just two keyword
arguments. Just the ones I want to change. The reason I do this is because it
is easier for me to read later on. I can just look and see that I&#8217;m only
changing options 1 and 5. I think that later on for me at least it is easier to
read.</p>

<h5>How to find keyword argument names</h5>

<p>I&#8217;ve looked up the documentation to find how to define each of these things.
The way I find the documentation is inside PSSE 32, in the help topics there
is a PDF. There is a line in there called Application Program Interface or
API. Which is the Python connection to PSSE.</p>

<p>If I look inside the menu here on the side and go down to <code>fnsl</code>, this is the
definition of that function in the documentation. I can see the Python syntax
<code>fnsl</code> and a named argument called <code>options</code>. A unique quality of PSSE is that
you can refer to each of the option list elements as a keyword argument. So
1,2,3,4,5,6,7 and 8 each of these options can be addressed individually.
Python keyword arguments cannot have brackets <code>()</code>. So I write <code>options1</code> all
lower case. It corresponds to the tap adjustments flag. The docs tell you what
values 0, 1 and 2 mean. I&#8217;ve used value 0 which means disable tap stepping,
the default is 1 (tap stepping enabled) and another value is 2 (direct tap
stepping).</p>

<p><code>options5</code> is a switched shunt adjustment flag. I&#8217;ve disabled the flag which is
value 0.</p>

<p>These keyword arguments start at 1 not zero. Normally in Python indexing
starts at 0, however the PSSE keyword arguments start at one.</p>

<h5>The keywords are not always the word <code>options</code></h5>

<p>I&#8217;ll just show one more function, its the machine data changing function. If
we go to Power Data Flow Changing. Let&#8217;s head to <code>machine_data_2</code>, this function
has four arguments. This one <code>intgar</code> and <code>realar</code> are lists of arguments. <code>intgar</code>
is an array of 6 elements. If I wanted to change the machine status I might
say <code>intgar1=0</code>. The <code>intgar</code> ones are normally integers and the <code>realar</code> ones are
floating point numbers.</p>

<p>So thats how I found the keyword arguments for the <code>fnsl</code> function.</p>

<p>If you have any questions about setting up keyword arguments for your PSSE
functions, get onto
<a href="https://psspy.org/psse-help-forum/questions/">https://psspy.org/</a> and ask a question
(it&#8217;s free).</p>

<div id="wufoo-m7x3w7">
Ideas for <a href="http://whitau.wufoo.com/forms/m7x3w7">Python videos</a>.
</div>


<script type="text/javascript">var m7x3w7;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'whitau', 
'formHash':'m7x3w7', 
'autoResize':true,
'height':'437',
'async':true,
'header':'show'};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { m7x3w7 = new WufooForm();m7x3w7.initialize(options);m7x3w7.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Solve a loadflow with PSSE]]></title>
    <link href="http://www.whit.com.au/blog/2012/12/solve-a-loadflow-with-psse/"/>
    <updated>2012-12-29T12:21:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/12/solve-a-loadflow-with-psse</id>
    <content type="html"><![CDATA[<p>I&#8217;ve been asked many times: &#8220;How do I solve a loadflow with Python?&#8221; It&#8217;s a
great question because once you know how to solve a loadflow - you can begin
to automate your PSSE work.</p>

<p>This video will show you exactly how to solve a PSSE loadflow using the full
newton raphson solution.</p>

<!--more-->




<iframe width="1280" height="720" 
    src="http://www.youtube.com/embed/xh4dbrNiwj0" frameborder="0" 
    allowfullscreen></iframe>


<p>If you want to see more tutorial posts like this: Tell us what topic you&#8217;d
like covered using <a href="#wufoo-m7x3w7">this form</a></p>

<h4>Transcript</h4>

<p>Hi there power systems engineers, today I&#8217;m going to show you how to solve a
load flow in Python using PSSE. In the last lesson we looked at
<a href="http://www.whit.com.au/blog/2012/10/import-psse-into-your-python-script/">how to set up your PSSE script</a> so that you
could run PSSE from Python and not the other way around.</p>

<p>So I&#8217;m going to build on that script and add the capability to run a load flow
and then say how many iterations that last load flow took to solve.</p>

<p>I&#8217;ve set up the script in the same way as the last video. We&#8217;ve changed the
python path so that python knows where to find the <code>psspy</code> library. and I&#8217;ve
<code>redirect</code>ed PSSE output to python.</p>

<h5>Initialise PSSE</h5>

<p>Just run <code>psseinit</code> to initialise psse. If you run the
program you find that you get that psse initialise text.</p>

<h5>Load a saved case</h5>

<p>To solve a case you first need one loaded in memory.
To load the saved case  use the <code>case</code> function. I&#8217;m just using the example
saved case that comes with PSSE <code>savnw.sav</code>.</p>

<p>If I run this again we see that the <code>savnw</code> case is loaded in memory and
was correctly loaded.</p>

<h4>Solve the saved case with fnsl</h4>

<p>The next step is to solve it, and print a little message to the
screen. That says the number of iterations in the last solution. I&#8217;m using the
Full Newton Raphson solution.</p>

<p>I&#8217;m using the <code>iterat</code> function. The <code>iterat</code> function gives the number of
iterations the last solution took to solve. And we substitute this value into
the string with the percent &#8216;s&#8217; (<code>%s</code>).</p>

<p>Here we can see there were 6 iterations, and my last print statement shows the
number of iterations was 6.</p>

<h5>Conclusion and sneak peak at the next video</h5>

<p>That is how easy it is to run a full newton raphson solution. I can run with
other options, I can run with taps stepping disabled and I can disable
switched shunt adjustments as well.</p>

<p>The answer should be the same in this file, but that may not be true of your
files. I knew that these options, <code>options1</code> and <code>options5</code> existed, and I&#8217;ll
show you how I found them in the next video.</p>

<p>If you have any questions about how to solve a load flow with Python, get onto
<a href="https://psspy.org/psse-help-forum/questions/">https://psspy.org/</a> and ask a question
(it&#8217;s free).</p>

<div id="wufoo-m7x3w7">
Ideas for <a href="http://whitau.wufoo.com/forms/m7x3w7">Python videos</a>.
</div>


<script type="text/javascript">var m7x3w7;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'whitau', 
'formHash':'m7x3w7', 
'autoResize':true,
'height':'437',
'async':true,
'header':'show'};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { m7x3w7 = new WufooForm();m7x3w7.initialize(options);m7x3w7.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Import PSSE into your Python script]]></title>
    <link href="http://www.whit.com.au/blog/2012/10/import-psse-into-your-python-script/"/>
    <updated>2012-10-29T12:52:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/10/import-psse-into-your-python-script</id>
    <content type="html"><![CDATA[<p>Here is a short video based on the tutorial in <a href="http://www.whit.com.au/blog/2011/07/run-psse-from-python-and-not-other-way/">running PSSE from Python</a></p>

<!--more-->




<iframe width="1280" height="720" 
    src="http://www.youtube.com/embed/nHrAAnCSYqU" frameborder="0" 
    allowfullscreen></iframe>


<h4>Transcript</h4>

<p>A look at importing Python into PSSE. Have you ever tried to <code>import psspy</code>
into your Python script only to see <code>ImportError: no module named psspy</code>.</p>

<p>That means that Python was not able to find the <code>psspy</code> installation. Even
though <code>psspy</code> comes with PSSE <em>and</em> we have Python installed on our computer.
Python still can&#8217;t find it, and that is because Python is a completely separate
program to PSSE.</p>

<h5>Telling Python where PSSE is installed</h5>

<p>We&#8217;re going to need to tell Python where PSSE is installed.</p>

<p>I&#8217;m going to import the operating system and system modules. I&#8217;m defining a
variable <code>PSSE_PATH</code> which is where the PSSE that I have is installed. Yours
might be different if you are using PSSE version 33, or if you are running 64 bit
Windows.</p>

<p>Python has a <code>sys.path</code> which is a list of directories that it looks in. When
you type in <code>import</code> it looks through every single one of these directories for
the file that you have said to import. So later on where I&#8217;ve typed in <code>import psspy</code>
Python will look through all of the directories and finally the one
I&#8217;ve appended at the end <code>PSSE_PATH</code> will contain the <code>psspy</code> module.</p>

<h5>Tell PSSE where PSSE is installed</h5>

<p>We could run this program now and Python would find <code>psspy</code>. However we need to
do one more thing. We need to tell PSSE where to find itself. PSSE is <em>strange</em>
in that we need to set the environment variable PATH. We need to add to the
end of that the PSSE installation path.</p>

<p>I&#8217;m not sure why PSSE needs to be told where it is, but your programs will
crash at some point if you haven&#8217;t done that step.</p>

<h5>Finally initialise PSSE</h5>

<p>Let&#8217;s initialise with 100 buses. We can see that PSSE is in fact running.</p>

<p>That is how you can import PSSE into your python scripts. So that you can run
the scripts from inside or outside of PSSE. You&#8217;ll notice that I didn&#8217;t open
up the PSSE application at any point.</p>

<p>If you have any questions about how to solve a load flow with Python, get onto
<a href="https://psspy.org/psse-help-forum/questions/">https://psspy.org/</a> and ask a question
(it&#8217;s free).</p>

<div id="wufoo-m7x3w7">
Ideas for <a href="http://whitau.wufoo.com/forms/m7x3w7">Python videos</a>.
</div>


<script type="text/javascript">var m7x3w7;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'whitau', 
'formHash':'m7x3w7', 
'autoResize':true,
'height':'437',
'async':true,
'header':'show'};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { m7x3w7 = new WufooForm();m7x3w7.initialize(options);m7x3w7.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Electricity Hedge Contracts Save Money In Volatile Australian Market]]></title>
    <link href="http://www.whit.com.au/blog/2012/10/electricity-hedge-contracts-save-money-in-volatile-australian-market/"/>
    <updated>2012-10-23T13:38:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/10/electricity-hedge-contracts-save-money-in-volatile-australian-market</id>
    <content type="html"><![CDATA[<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh4.googleusercontent.com/-unMA5BtEK7k/UD_YXA_PVFI/AAAAAAAA1sI/l73X0rclT98/s300/IMAG0449.jpg" width="300" title="Hedge contracts are for large consumers" >
</td></tr><tr><td style="text-align: center; width: 300px;">Hedge contracts are for large consumers </td></tr></tbody></table>


<p>Last week, we investigated how a
<a href="http://www.whit.com.au/blog/2012/10/will-a-pool-pass-through-contract-reduce-your-electricity-bill/">pool pass through contract could save you money</a>.
We concluded that when market conditions
are favourable, your electricity bill will be lower if you take the pool
price. That post raised some discussion about what if hedge contracts had been
purchased instead.</p>

<p>In this post we investigate how hedging your electricity contract can insure
you against the volatility of the market.</p>

<!-- more -->


<h4>Large consumers buy hedge contracts</h4>

<p>We&#8217;ll analyst the costs for a single large energy consumer. This customer has
40 MW of installed machinery. Example customers of this size (and larger)
might be:</p>

<ul>
<li>Steelworks;</li>
<li>An aggregation of supermarkets or shopping centers; and</li>
<li>Utility water companies</li>
</ul>


<p>The minimum purchase price for a hedge contract from
<a href="http://d-cyphatrade.com.au/">d-cypha trade</a> is 1 MW.
If your peak electricity usage isn&#8217;t over 1 MW, purchasing your own hedge
contracts wont save you any money. But I&#8217;m sure a long talk with your
electricity retailer would - we&#8217;ve been told that rates for higher using
consumers are extremely competitive right now.</p>

<h4>MW or MWh, what is the difference <a id="fr1" href="#fn1">[ 1 ] &darr;</a></h4>

<h4>What is the right amount of peak and base to buy?</h4>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh6.googleusercontent.com/-pKEEYWnnWwU/UITsHG9lwZI/AAAAAAAA3g4/uOU-gr89Zx0/s300/profile.png" width="300" title="Buy hedge contracts to fit your profile" >
</td></tr><tr><td style="text-align: center; width: 300px;">Buy hedge contracts to fit your profile <a href="https://lh6.googleusercontent.com/-pKEEYWnnWwU/UITsHG9lwZI/AAAAAAAA3g4/uOU-gr89Zx0/s720/profile.png" target="_blank">[Full Size]</a> </td></tr></tbody></table>


<p>Here is the daily load profile for the industrial consumer. Consumption is low
overnight, typically below 14 MW. At 7 am production quickly ramps up to full
output (around 38 MW). Then production finishes around 10 PM at night.</p>

<p><em>Peak contracts cover your usage between 7am to 10pm</em> seven days a week. So if
your facility uses more power during these times (like our example large
consumer), it will be a good fit for a peak contract. <em>Base contracts cover
all hours of the day</em> seven days a week. Base contracts are good for
consumption that occurs consistently day and night. Our example consumer&#8217;s
consumption doesn&#8217;t drop below 14 MW.</p>

<h4>Buying a 14 MW base contract</h4>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh4.googleusercontent.com/-fp-Dt0ZYaII/UIXj8En2flI/AAAAAAAA3hI/TFK4IxyD_Pw/s300/contract-vs-usage.png" title="The sum of our two hedge contracts fit the peak" >
</td></tr><tr><td style="text-align: center; width: 300px;">The sum of our two contracts cover the peak <a href="https://lh4.googleusercontent.com/-fp-Dt0ZYaII/UIXj8En2flI/AAAAAAAA3hI/TFK4IxyD_Pw/s720/contract-vs-usage.png" target="_blank">[Full Size]</a> </td></tr></tbody></table>


<p>The consumption doesn&#8217;t drop below 14 MW. Imagine creating a rectangle 14 MW
high on the daily profile chart. We&#8217;ve drawn it in green. It represents the
base contract. Buying a 14 MW base contract means that we have agreed to pay
for 14 MW at $X for every half hour in the day. Even if our machines break-
down, or we take a vacation and shut down the plant, we still pay for that 14
MW.</p>

<h4>Buying a 22 MW peak contract</h4>

<p>The consumption between 7am and 10pm rises to between 37 MW and 38 MW. We&#8217;ve
already purchased 14 MW with the base contract, which leaves 23 MW outside of
contract. Buying 23 MW of another <em>base</em> contract would be wasteful in the
extreme,  because we don&#8217;t use that additional 23 MW at night. Instead we&#8217;ll
purchase a <em>peak</em> contract for 22 MW (leaving 1-2 MW to take on spot market
risk). We opted for 22 MW because the usage fluctuates above and below 23 MW,
and we couldn&#8217;t purchase 22.5 MW because dcypha only trade contract units of 1
MW.</p>

<h4>Making and losing money. A tail of two quarters.</h4>

<p>We&#8217;ll investigate the cost of the hedge contracts over two financial quarters
in 2012:</p>

<ul>
<li>The first from April to June; and</li>
<li>The second from July to September.</li>
</ul>


<p>The following analysis assumes the hedge prices <a id="fr2" href="#fn2">[ 2 ] &darr;</a> :</p>

<ul>
<li>base contract: $48 / MWh; and</li>
<li>peak contract: $54 / MWh.</li>
</ul>


<p>In the first quarter (<strong>April to June 2012</strong>). The total energy costs (both
hedges and spot market rates for the energy outside of contract) were $3.28M.
The equivalent if all energy was purchased from the spot market was $2.18M.</p>

<p>The second quarter (<strong>July to September 2012</strong>). The total energy costs were
$3.44M. The equivalent if all energy was purchased from the spot market was
$4.18M.</p>

<div>
  <style>
     table.ztab1 {
        margin: auto;
        font-size: 70%;
        border: 1px solid black;
      }

      table.ztab1 th {
        font-weight: bold;
        background-color: steelblue;
        text-align: center;
        border-bottom: 2px solid black;
      }

      table.ztab1 th,td {
        padding: 4px 5px;
      }

      table.ztab1 tr:nth-of-type(odd) {
        background-color: lightsteelblue;
      }

      table.ztab1 tr:nth-of-type(even) {
        background-color: cornflowerblue;
      }
  </style>
</div>




<table class="ztab1">
    <tr>
        <th>Contract Period</th>
        <th>Spot market</th>
        <th>With hedging</th>
    </tr>
    <tr>
        <td>April - June 2012</td>
        <td>$2.18M</td>
        <td>$3.26M</td>
    </tr>
    <tr>
        <td>July - September 2012</td>
        <td>$4.18M</td>
        <td>$3.44M</td>
    </tr>
</table>


<h4>Paying for predictable pricing</h4>

<p>A set of hedge contracts that fit your load profile can save money when the
market becomes volatile. However when markets produce stable prices it is best
to buy directly from the pool.</p>

<p>The trouble is, who knows how to predict whether the next quarter will be
volatile or stable? If you can predict the volatility of future quarters, give
us a call, we&#8217;d love to talk :)</p>

<p>You <em>must</em> purchase contracts that fit the shape of your load (or perhaps
change the shape of your load to fit the contracts). Because once you are
contracted for 14 MW, you must pay for those 14 MW whether you used them or
not. An ill-fitting contract shape can cost you more than the volatility it
protects you against.</p>

<p>Finally, if your consumption doesn&#8217;t rise above 1 MW for at least the peak
hours, then it isn&#8217;t worthwhile purchasing a hedge contract yourself. This is
what retailers are for. They pool all of their customers together and purchase
large hedge contracts.</p>

<p>If you have some ideas for further investigation let us know in the comments</p>

<div id="wufoo-m7x3w7">
Ideas for <a href="http://whitau.wufoo.com/forms/m7x3w7">further investigation</a>.
</div>


<script type="text/javascript">var m7x3w7;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'whitau', 
'formHash':'m7x3w7', 
'autoResize':true,
'height':'437',
'async':true,
'header':'show'};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { m7x3w7 = new WufooForm();m7x3w7.initialize(options);m7x3w7.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>


<h4>Footnotes</h4>

<h5>MW or MWh, what is the difference? <a id="fn1" href="#fr1">[ 1 ] &uarr; </a></h5>

<p>A MW (Mega-watt, 1 million watts) is an amount of energy consumed per second.
Often pumps and generators have a nameplate with the MW rating written on it.
Light bulbs are rated by their power consumption too. 20W to 100W being common
around the family home.</p>

<p>A MWh (Mega-watt hour) is the standard measure of
energy in the electricity market. Running a 1 MW pump for 1 whole hour will
consume 1 MWh, running for half an hour will consume 0.5 MWh. And running a
100W light bulb for an hour will consume 0.0001 MWh.</p>

<p>I normally talk in terms of MW when giving the size of a facility, because it
aligns with the ratings given for large equipment. Your electricity bill is
for energy consumed (MWh) not your instantaneous power (MW).</p>

<h5>Why $48 / MWh and $54 / MWh? <a id="fn2" href="#fr2">[ 2 ] &uarr;</a></h5>

<p>We estimated that contracts in Victoria could have been purchased at these
values for the 2012 year. To understand how the contract price has been changing
we read through some of the &#8221;<a href="http://d-cyphatrade.com.au/market_wrap">market wrap</a>&#8221;
reports written by d-cypha trade.</p>

<p>The second quarter was volatile notably because of the
<a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">introduced carbon price</a>.
But we used the same contract prices assuming that they had been purchased
well in advance, you can&#8217;t get such low prices on hedge contracts any more.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Will a pool pass through contract reduce your electricity bill?]]></title>
    <link href="http://www.whit.com.au/blog/2012/10/will-a-pool-pass-through-contract-reduce-your-electricity-bill/"/>
    <updated>2012-10-16T13:25:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/10/will-a-pool-pass-through-contract-reduce-your-electricity-bill</id>
    <content type="html"><![CDATA[<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh6.googleusercontent.com/-42iBRc3k_2s/UB_lX1e75cI/AAAAAAAA1UI/ktrapGg7yKs/s400/IMG_6484.JPG" width="300" title="Electricity prices vary throughout the day" >
</td></tr><tr><td style="text-align: center; width: 300px;">Electricity prices vary throughout the day </td></tr></tbody></table>


<p>We investigate the raw cost of electricity. How much profit does a retailer
make in selling us electricity?</p>

<p>Not everyone will find this article interesting. Because not everyone has a
huge electricity bill or works in the electricity industry. If your
electricity usage is greater than 50000 kWh / year (the equivalent usage of
ten small families) then this is for you.</p>

<p>For those not reading on: Conclusion, A pool pass through contract could save
24% on your annual electricity bill. But by doing so you take on wholesale
market risk instead of your retailer, and we note that in recent months it may
have been more profitable to be on a fixed contract due to the large spike in
volatility after the carbon price introduction.</p>

<!--more-->


<h4>The wholesale price for electricity varies every half hour</h4>

<p>For a period during the 2000s I worked for the Australian National Electricity
Market operator (then called NEMMCO now AEMO) and became fascinated with the
wholesale electricity market. In most countries now, there exists a market
based system for pricing electricity. In Australia that wholesale price
changes every half an hour.</p>

<p>But most retail electricity contracts have a flat rate price per kWh used.
Your retailer is buying electricity at the varying wholesale rates, and
selling to you at a fixed flat rate. Your retailer takes the risk and they
don&#8217;t take risks out of the kindness of their heart. The risks are carefully
evaluated and priced into the flat rate. Your flat rate covers:</p>

<ul>
<li>The raw price of electricity</li>
<li>The wholesale market risk</li>
<li>Administration and overhead; and</li>
<li>Retailer profits</li>
</ul>


<h4>A pool pass through exposes you to the wholesale electricity market</h4>

<p>The pool pass through contract is the name of a deal you can make with your
retailer where you pay the varying wholesale rates, instead of the guaranteed
$0.24 / kWh.</p>

<p>Those wholesale prices vary from <em>negative</em> $1 / kWh, where <strong>you get paid to
use more electricity</strong> - up to $12.50 / kWh. The price normally hovers between
$0.04 / kWh and $0.06 / kWh.</p>

<p>These pool pass through deals were not popular for a very long time.
Businesses were more interested in a flat predictable electricity bill than
one which can be higher in summer and lower in winter. But all of that is
changing and businesses are beginning to ask for pool pass through contracts.</p>

<h4>Businesses may be moving away from pool pass through contracts</h4>

<p>There has been a surge of volatility with the introduction of the recent carbon
price in the Australian market
(see <a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">All you need to analyse the electricity market pt 1</a>)
The general trend for the last two years was that businesses were asking for a
pool pass through contract. Contrast this with the last few months, some
businesses have regretted that decision. The recent volatility made the fixed
price plans offered to the highest volume customer cheaper than riding the
wholesale market.</p>

<p>Throughout the analysis bear in mind that a very large consumer (one spending
hundreds of thousands on electricity per year) would be offered <strong>much</strong>
better rates than $0.24 / kWh. Accepting wholesale market risk might work well
in the years with low volatility, but could be an unacceptable burden for your
short term cash flow when volatile periods happen.</p>

<h4>Meet the worst kind of customer</h4>

<p>We&#8217;ll run some calculations to see what the raw cost of the underlying
electricity is on a pool pass through contract. But to do that we need an
example customer. Meet Jill, the worst kind of customer.
Jill uses the most electricity during the middle of the day
when the prices are at their highest. Can Jill save money on a pool
pass through contract? Yes. Read on to find out how much.</p>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh4.googleusercontent.com/-FmTPyGMS8z4/UHyux1zcvvI/AAAAAAAA3go/rfc_XuO8-3w/s320/electricity-usage-profile.png" width="300" title="Jill's usage profile on a typical weekday" >
</td></tr><tr><td style="text-align: center; width: 300px;">Jill&#8217;s usage profile on a typical weekday <a href="https://lh4.googleusercontent.com/-FmTPyGMS8z4/UHyux1zcvvI/AAAAAAAA3go/rfc_XuO8-3w/s720/electricity-usage-profile.png">[Larger Size]</a></td></tr></tbody></table>


<p>Here is Jill&#8217;s electricity usage profile. She uses 5000 kWh per year and is a
smaller sized business. Her cost per year is $1245 including a generous 10%
off discount from Origin energy. Jill&#8217;s company is a small design firm, and
the electricity is mostly made up of the office computers, lights and cooling.</p>

<h4>A saving of 24%</h4>

<p>We calculated the base wholesale electricity cost had she been on a pool pass
through contract for the last financial year (ending 30 June 2012) and made the
following adjustments:</p>

<ul>
<li>Added $0.023 / kWh to account for the price of carbon which was introduced since July 2012.</li>
<li>Added a $0.80 / day electricity supply charge</li>
</ul>


<p>The raw cost of electricity then is:</p>

<p> $562</p>

<p>This raw electricity price doesn&#8217;t account for the costs incurred by your
retailer in serving you electricity. The type of costs might be market fees,
administration and business overhead. We weren&#8217;t sure how to calculate these
costs. Instead we assumed that they could be around 50% of the total cost.
Adding in that 50% brings the total to:</p>

<p> $943</p>

<p>This is a reduction of around 24% on the already discounted retail price of $1245.</p>

<h4>What are the risks?</h4>

<p>A pool pass through contract comes with very serious risks. In fact, the saved
money is due to you taking on risk that your retailer previously faced.
Here are the risks that our example business will face:</p>

<ul>
<li>The electricity price could reach $12.5 / kWh. Our example businesses would
lose $3.60 for every hour that they ran under such high priced conditions.</li>
<li>A disaster could cause the wholesale price could unexpectedly remain high for a long time.</li>
<li>You could end up paying more in total for your electricity than if you were on a flat rate</li>
</ul>


<h4>Ride the wholesale ups and downs</h4>

<p>By riding the market ups and downs you (on average) will save money across the
year. And that saving will be equal to the price of risk that retailers
charge to you (and profited from).</p>

<p>If you are a large business paying $200,000 / year, your savings would be less
than the figures quoted here. The competition for very large businesses is
fierce right now. Retailer margins are extremely low, and they look to make up
their profit with volume.</p>

<p>Have a talk to your retailer and ask about their pool pass through plans.
Here are some questions to ask them:</p>

<ul>
<li>How much energy must I consume to be eligible for a pool pass through contract;</li>
<li>What are your fixed charges (administration fees); and</li>
<li>Does any portion of your costs vary with consumption (e.g. market fees)?</li>
</ul>


<p>Do you know something we don&#8217;t about pool pass through contracts? Have you
tried them in the past, how did it work out for you?</p>

<p>If you&#8217;d like a copy of the data we used or want to comment about pool pass
through contracts call us on (03) 8644 8163.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Export PSSE data to Excel]]></title>
    <link href="http://www.whit.com.au/blog/2012/10/export-psse-data-to-excel/"/>
    <updated>2012-10-15T11:14:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/10/export-psse-data-to-excel</id>
    <content type="html"><![CDATA[<p>Have you ever wanted to export data from PSSE into Microsoft Excel? In today&#8217;s post we&#8217;ll show you the exact steps that you need to export your data from PSSE directly into Microsoft Excel using Python.</p>

<!--more-->




<iframe width="560" height="315" src="http://www.youtube.com/embed/WCRg7Pc_6_0?rel=0" frameborder="0" allowfullscreen></iframe>


<p>If you want to see more tutorial posts like this: Tell us what topic you&#8217;d like covered using <a href="#wufoo-m7x3w7">this form</a></p>

<h4>Transcript</h4>

<p>Hello Power systems engineers. Have you ever wanted to control Microsoft Excel from Python? What about exporting data from PSSE into Microsoft Excel? Well today you&#8217;ll learn how to do both of these things: Control Excel from Python and export from PSSE. Lets get started.</p>

<p>I&#8217;ve opened up my Python shell here. And I&#8217;ve pointed it at the PSSE installation that I&#8217;m running which is PSSE 32.
I&#8217;ve added to the <code>PYTHONPATH</code> so <code>sys.path.append</code> which tells Python where to find the PSSE libraries. And the <code>os.environ</code> <code>PATH</code> addition tells PSSE where its own libraries are added. You will need both of these before you can start importing the next two steps.</p>

<h5>First connection to Excel</h5>

<p>So I&#8217;ve imported the <code>excelpy</code> module. This is distributed with PSSE version 32 and was written by the PSSE team. And it makes it easy to write data to Excel.</p>

<p>I&#8217;ll create an <code>excelpy</code> workbook. Now a workbook is just an Excel spreadsheet. And I&#8217;ll store a reference to that spreadsheet in a variable I am going to call <code>xl</code>. And I can show that new Excel spreadsheet and it appears on the right as <code>book4</code>.</p>

<h5>Write a heading to Excel</h5>

<p>I can write headings. So for instance to write a heading &#8220;bus numbers&#8221; to cell A1 I use the <code>set_cell</code> method. I can also set a heading in the second column to &#8220;voltage (p.u)&#8221;.</p>

<h5>Export data from PSSE to Excel</h5>

<p>Now lets export some data from PSSE and put here into Excel. I&#8217;m going to export two sets of data:
 - First all of the bus numbers in the demonstration saved case;
 - Followed by all of the per unit voltages for those bus numbers.</p>

<p>So first let&#8217;s get a list of all the bus numbers.
First we&#8217;ll <code>import psspy</code> and <code>import redirect</code>.</p>

<p>We&#8217;ll use <code>redirect.psse2py</code> to change any text from appearing in pop up dialog boxes to being in the actual Python shell here.
(<em>Jervis notes</em> If you forget to run <code>redirect.psse2py</code> you will see a series of incredibly annoying pop up boxes created by PSSE)</p>

<p>Now I&#8217;ve initialised PSSE and you can see the output has been put here into this PSSE shell rather than in any pop up boxes.</p>

<p>Now with PSSE initialised let&#8217;s load a case. And then read out a list of all the bus numbers. The bus numbers have been stored in a variable called <code>buses</code>.</p>

<p>I&#8217;ve used a function called <code>abusint</code> which is one of the subsystem data retrieval functions. The subsystem data retrieval functions let you access a whole host of data for all of the buses at once rather than one at a time.
(<em>Jervis notes</em> the subsystem data retrieval functions are incredibly powerful - but can be difficult to use and understand because of the way PSSE wrote them. See our post on <a href="http://www.whit.com.au/blog/2011/08/designing-easier-subsystem-data/">Designing an easier subsystem data retrieval API</a> for an alternative that you can use yourself)</p>

<p>You can do the same to get the voltages. And here I&#8217;ve collected the voltages in per unit.</p>

<p>Now to write this column of buses and column of voltages into Excel. So I&#8217;m going to set the range from row 2 in column A to be the buses. And, the voltages in column B. Now I&#8217;ve used the <code>zip</code> function to transpose what was given to me by PSSE as a row into a column.</p>

<p>Now we can save our workbook.</p>

<p>So that&#8217;s it for now.
If you have any questions about exporting data into Excel. Feel free to hop onto <a href="http://psspy.org/psse-help-forum/questions/">http://psspy.org</a> and ask your question. I&#8217;d be happy to answer.</p>

<div id="wufoo-m7x3w7">
Ideas for <a href="http://whitau.wufoo.com/forms/m7x3w7">Python videos</a>.
</div>


<script type="text/javascript">var m7x3w7;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'whitau', 
'formHash':'m7x3w7', 
'autoResize':true,
'height':'437',
'async':true,
'header':'show'};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { m7x3w7 = new WufooForm();m7x3w7.initialize(options);m7x3w7.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[CAISO response to Pay for Performance in electricity market]]></title>
    <link href="http://www.whit.com.au/blog/2012/08/caiso-response-to-pay-for-performance-in-electricity-market/"/>
    <updated>2012-08-22T10:29:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/08/caiso-response-to-pay-for-performance-in-electricity-market</id>
    <content type="html"><![CDATA[<p>Find out how the new performance payments system can be gamed for profit and
CAISO&#8217;s response to these claims.</p>

<!-- more -->


<h4>Background - Order 755</h4>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh4.googleusercontent.com/-fSp3gFufEWo/UB_QT9mDH0I/AAAAAAAA1UM/icxGLVM2W9E/s567/IMG_6062.JPG" width="300" title="CAISO replys to FERC Order 755 report" >
</td></tr><tr><td style="text-align: center; width: 300px;">CAISO sceptical that markets can be gamed <a href="https://lh4.googleusercontent.com/-fSp3gFufEWo/UB_QT9mDH0I/AAAAAAAA1UM/icxGLVM2W9E/s567/IMG_6062.JPG">[Larger Size]</a> </td></tr></tbody></table>


<p>The <a href="http://www.caiso.com/informed/Pages/BoardCommittees/MarketSurveillanceCommittee/Default.aspx">CAISO Market Surveillance Committee</a>
believes that there are market inefficiencies in the Californian Electricity
Market.</p>

<p>This news follows the Federal Energy Regulatory Commission&#8217;s passing
<a href="http://www.caiso.com/informed/Pages/StakeholderProcesses/PayforPerformanceRegulation.aspx">Order 755</a>
which relates to payments made for controlling the security of the electricity
market.</p>

<h4>What are regulation payments?</h4>

<p>Every second of the day the electricity system must be in perfect balance. For
every house using a kettle, there must be an equivalent amount supplied from a
wind turbine, or a power plant somewhere.</p>

<p>If there is not enough power supply, the whole power system begins to slow
down. Just like if you were riding your bike, and encountered a hill but
didn&#8217;t pedal any harder. Eventually the system is too slow and will fall over
(like you would come off your bike).</p>

<p>CAISO already knows this. So they have generators everywhere on standby to
produce little bits more energy to constantly balance things out. This system
of balancing is called <em>regulation</em>.</p>

<p>Regulation payments are the system CAISO uses to pay generators for providing
this balancing service.</p>

<h4>What is Order 755?</h4>

<p>FERC has given Independent System Operators like CAISO a short period of time
to comply with their new policy: To pay generators for two things relating to
regulation:</p>

<ol>
<li>Just for being available, a capacity payment</li>
<li>For doing their job and actually balancing the power, a mileage payment</li>
</ol>


<p>Generators all bid against each other to say: &#8220;I&#8217;m available for $X per hour
and you need to pay me $Y per MW when I actually change my output to balance
the power.&#8221;</p>

<h4>Can the new payments system be gamed?</h4>

<p>The Market Surveillance Committee says yes it can. Here is how:</p>

<h5>Offer a low capacity price</h5>

<p>The CAISO currently evaluates regulation offers by the lowest capacity price
(not the new mileage price). So step one is to offer a very low capacity price
so that you are selected to provide regulation services.</p>

<h5>Quickly take all of the mileage payments.</h5>

<p>The mileage payments are the amount of work you do to balance. Say there was a
deficit of 100 MW and you were to increase output by 20 MW. You would get paid
the mileage rate for that 20 MW. Everyone else would share in the remaining 80
MW. But what if you were quick, and could provide the entire 100 MW? Then
that&#8217;s great; you get all of the mileage payments. And because you bid those
payments yourself you can set whatever price you want.</p>

<h4>The Market Management Council&#8217;s response</h4>

<p>The <a href="http://www.caiso.com/Documents/Department_MarketMonitoringReport-MAR2012.pdf">opinion of the MMC (PDF)</a> is that the divergence of capacity and mileage payments
creates market inefficiencies.</p>

<p>However, the gaming issues identified are unlikely to cause a problem in the
short term. Strong competition should keep prices in check. There are few, if
any fast enough resources capable of providing regulation. The available fast
ramping resources are hydro power plants  and all of the hydro plants are
owned by regulated load serving entities. So they don&#8217;t think any market
participants will actually game the system.</p>

<h4>Can the system be gamed?</h4>

<p>We aren&#8217;t sure, the money changing hands in the regulation market is much
lower than in the traditional wholesale electricity market, so there might be
less incentive. The MMC&#8217;s reply to the possibility for market gaming didn&#8217;t
seem alarmed. They have a market monitoring procedure in place that should
pick up on irregularities.</p>

<p>The MMC asserts that a regulated load serving entity wouldn&#8217;t take advantage
of the new market design to increase their profit. We find that to be
interesting because we&#8217;ve seen evidence in other markets that even Government-
owned businesses still profit from market power when they can.</p>

<p>Is there currently a way to game the Californian electricity market to
increase profit? Are energy companies now silently boosting their profits by
exerting their market power? What do you think?</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Did Germany's solar power output just double in two years?]]></title>
    <link href="http://www.whit.com.au/blog/2012/08/did-germanys-solar-power-output-just-double-in-two-years/"/>
    <updated>2012-08-21T13:23:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/08/did-germanys-solar-power-output-just-double-in-two-years</id>
    <content type="html"><![CDATA[<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh4.googleusercontent.com/-gSJo_upf7-g/UCzd_tBL-NI/AAAAAAAAAOE/dNxiQ-eMuVw/s800/ampiron.png" width="400" title="Solar power production increases since 2010 in Amprion's region" >
</td></tr><tr><td style="text-align: center; width: 400px;">Peak solar output increases over a two year period <a href="https://lh4.googleusercontent.com/-gSJo_upf7-g/UCzd_tBL-NI/AAAAAAAAAOE/dNxiQ-eMuVw/s800/ampiron.png">[Larger Size] </td></tr></tbody></table>


<p>We found in a recent survey that peak solar power production in Amprion&#8217;s network
has <strong>more than doubled</strong> since 2010.</p>

<h4>An attractive investment</h4>

<p>Sizeable increases have been attributed to the attractive feed-in tariff scheme set
up by the German government.</p>

<p>The German solar industry is supported by feed in tariffs paid to solar
energy producers. Solar farm owners of less than 10MW in size are paid
handsomely for every kWh of energy they produce.</p>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh5.googleusercontent.com/-xD0yt_plATg/UCzbgCsu2KI/AAAAAAAAAN4/QqhU0wiiiNU/s567/deutscher_regions.png" width="300" title="Taken from de.wikipedia.org" >
</td></tr><tr><td style="text-align: center; width: 300px;">Amprion&#8217;s transmission region <a href="https://lh5.googleusercontent.com/-xD0yt_plATg/UCzbgCsu2KI/AAAAAAAAAN4/QqhU0wiiiNU/s567/deutscher_regions.png">[Larger Size]</a> </td></tr></tbody></table>


<p>According to <a href="http://www.germanenergyblog.de/?p=9756">http://www.germanenergyblog.de/?p=9756</a>
owners are paid between 13.1 and 19.92 European cents per kWh produced.</p>

<p>These payments are guaranteed for the next 20 years. The investment situation
is very stable and banks love it.</p>

<h4>Abandoning Nuclear power</h4>

<p>The German government plans to abandon nuclear power by 2022. Nuclear plants
produced about a third of Germany&#8217;s power, this leaves a large gap that
renewable energy can fill. We think that the solar power production in
Amprion&#8217;s transmission region will rise still higher in the future.</p>

<p>Do you think solar power output will have doubled again in two years time?</p>

<h4>How did you get the solar production data?</h4>

<p>The main focus of this blog is to make you a better Python programmer in the
energy industry. Do you want to know where we found that solar power data?</p>

<p>Sign up for updates to our blog, we&#8217;ll cover it in the next post! Don&#8217;t miss it.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to maximise your croissant time at CIGRE Paris]]></title>
    <link href="http://www.whit.com.au/blog/2012/08/how-to-maximise-your-croissant-time-at-cigre-paris/"/>
    <updated>2012-08-09T12:44:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/08/how-to-maximise-your-croissant-time-at-cigre-paris</id>
    <content type="html"><![CDATA[<blockquote><p>[..] I have a fancy now: to have applications like this one [&#8230;] available for members interested</p><footer><strong>Francois Meslier</strong> <cite>CIGRE Secretary General</cite></footer></blockquote>




<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="http://www.cigre.org/var/cigre/storage/images/media/images/session-symposium/session-paris/15990-1-eng-GB/Session-Paris_news_full.jpg" width="300" height="44">
</td></tr><tr><td style="text-align: center; width: 300px;">the 44th CIGRE Paris has 444 paper presentations </td></tr></tbody></table>


<p>At the <a href="http://www.cigre.org/Events/Session/Session-2012/">44th CIGRE Paris</a>
this year, there are over 6000 engineers attending to see 444 paper
presentations held in 4 rooms concurrently.</p>

<p>But CIGRE isn&#8217;t just about the presentations, its a time to duck out mid-
session and take your loved one for a coffee, a time to meet with someone just
like you that works in the same job in another country.</p>

<p>How do you fit it all in, and not miss those 10-30 &#8220;must see&#8221; papers?</p>

<p>Now there is the <a href="http://www.whit.com.au/cigre/">CIGRE paper scheduler</a> A
place for you to search and find the papers that interest you, and see when
and where you need to be to watch the presentations. It has a calendar that
updates live as you select papers, showing you when your free times are so you
can schedule your own meeting on the Seine.</p>

<p>See you in Paris!</p>

<p>Used the CIGRE scheduler? We&#8217;re still improving it. What is <em>one</em> thing that you would
change?</p>

<div id="wufoo-m7x3w7">
Ideas for <a href="http://whitau.wufoo.com/forms/m7x3w7">CIGRE Paris form</a>.
</div>


<script type="text/javascript">var m7x3w7;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'whitau', 
'formHash':'m7x3w7', 
'autoResize':true,
'height':'437',
'async':true,
'header':'show'};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { m7x3w7 = new WufooForm();m7x3w7.initialize(options);m7x3w7.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[All you need to analyse the electricity market final]]></title>
    <link href="http://www.whit.com.au/blog/2012/08/all-you-need-to-analyse-the-electricity-market-final/"/>
    <updated>2012-08-08T22:37:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/08/all-you-need-to-analyse-the-electricity-market-final</id>
    <content type="html"><![CDATA[<p>If you are an electrical engineer, and want to know how to use Python
to get data from the Internet and display it, this post is for you.</p>

<p>This is the <em>final</em> part of a four part series. By the end we&#8217;ll have written a Python
script to display a chart of electricity market prices.</p>

<ul>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">All you need to analyse the electricity market pt 1</a></li>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-2/">All you need to analyse the electricity market pt 2</a></li>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-3/">All you need to analyse the electricity market pt 3</a></li>
<li>All you need to analyse the electricity market final</li>
</ul>


<h4>Australian electricity prices are high - let&#8217;s analyse</h4>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" width="300" title="Australian Electricity Prices are higher since the introduction of the carbon tax" >
</td></tr><tr><td style="text-align: center; width: 300px;">Very high electricity prices <a href="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" title="Larger View">[Larger Size]</a> </td></tr></tbody></table>


<p><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">Previously</a> I
mentioned that the Australian electricity prices have gone through the roof
(more than doubling) since the introduction of the carbon tax.</p>

<p>This series of posts is exploring how to analyse market data accessible from the
internet. The methods described can be adapted to your country&#8217;s data or any
sort of data available on the internet.</p>

<p>We began the series with a post detailing how to obtain a CSV file that
contains the latest electricity market prices.</p>

<p><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-2/">Then</a> we
unzipped the price data CSV file that was downloaded in Part 1 and had a brief
look at its contents.</p>

<p><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-3/">Then</a> we pulled that CSV file apart using Python.</p>

<p>Now you&#8217;ll plot the prices and system demand using <strong>matplotlib</strong>.</p>

<p>The code we have developed over this series so far:</p>

<ol>
<li>Downloads a zipped file;</li>
<li>Unzips it;</li>
<li>Reads the file contents as a CSV; and</li>
<li>Extracts the half hourly demand and price values.</li>
</ol>


<figure class='code'><figcaption><span>converted_data.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">datetime</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># assuming there is only one CSV in the zipped file.</span>
</span><span class='line'><span class="n">csv_filename</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_file</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">prices_csv_file</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">is_halfhourly_data</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;Returns True if the given row starts with &#39;D&#39;, &#39;TREGION&#39;, &#39;&#39;, &#39;1&#39;&quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">row</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="s">&quot;D&quot;</span><span class="p">,</span> <span class="s">&quot;TREGION&quot;</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">,</span> <span class="s">&quot;1&quot;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">halfhourly_data</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="n">is_halfhourly_data</span><span class="p">,</span> <span class="n">prices_csv_reader</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_date_region_and_rrp</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd">    Returns the SETTLEMENTDATE, REGION and RRP from the given</span>
</span><span class='line'><span class="sd">    PUBLIC_PRICES CSV data row.</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    SETTLEMENTDATE is converted to a Python date (the time is discarded);</span>
</span><span class='line'><span class="sd">    REGION is left as a string; and</span>
</span><span class='line'><span class="sd">    RRP is converted to a floating point.</span>
</span><span class='line'><span class="sd">    &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="s">&#39;%Y/%m/</span><span class="si">%d</span><span class="s"> %H:%M:%S&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">date</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span>
</span><span class='line'>            <span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">]))</span>
</span><span class='line'>
</span><span class='line'><span class="n">date_region_price</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">get_date_region_and_rrp</span><span class="p">,</span> <span class="n">halfhourly_data</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h4>The completed example</h4>

<p>Here is the complete code to download and plot the electricity prices with
Python. We&#8217;ll step through the most important parts and show you two of
Python&#8217;s advanced features <code>defaultdict</code> and <code>yield</code>.</p>

<p>If you aren&#8217;t interested in the advanced Python code, you can skip to the end.
The <strong>matplotlib</strong> code that creates the chart is very short and easy to
follow.</p>

<figure class='code'><figcaption><span>final.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">datetime</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="kn">as</span> <span class="nn">plt</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'><span class="n">REGIONS</span> <span class="o">=</span> <span class="p">(</span><span class="s">&quot;QLD1&quot;</span><span class="p">,</span> <span class="s">&quot;NSW1&quot;</span><span class="p">,</span> <span class="s">&quot;VIC1&quot;</span><span class="p">,</span> <span class="s">&quot;SA1&quot;</span><span class="p">,</span> <span class="s">&quot;TAS1&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="k">try</span><span class="p">:</span>
</span><span class='line'>    <span class="n">zippedfile</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">ZIP_URL</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">))</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'><span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span>
</span><span class='line'>    <span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>    <span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">ZIP_URL</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">),</span> <span class="s">&#39;wb&#39;</span><span class="p">)</span>
</span><span class='line'>    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># assuming there is only one CSV in the zipped file.</span>
</span><span class='line'><span class="n">csv_filename</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_file</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">prices_csv_file</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">is_halfhourly_data</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;Returns True if the given row starts with &#39;D&#39;, &#39;TREGION&#39;, &#39;&#39;, &#39;1&#39;&quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">row</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="s">&quot;D&quot;</span><span class="p">,</span> <span class="s">&quot;TREGION&quot;</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">,</span> <span class="s">&quot;1&quot;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">halfhourly_data</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="n">is_halfhourly_data</span><span class="p">,</span> <span class="n">prices_csv_reader</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_date_region_and_rrp</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd">    Returns the SETTLEMENTDATE, REGION and RRP from the given</span>
</span><span class='line'><span class="sd">    PUBLIC_PRICES CSV data row.</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    SETTLEMENTDATE is converted to a Python date (the time is discarded);</span>
</span><span class='line'><span class="sd">    REGION is left as a string; and</span>
</span><span class='line'><span class="sd">    RRP is converted to a floating point.</span>
</span><span class='line'><span class="sd">    &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="s">&#39;%Y/%m/</span><span class="si">%d</span><span class="s"> %H:%M:%S&#39;</span><span class="p">),</span>
</span><span class='line'>            <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span>
</span><span class='line'>            <span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">]))</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">get_date_region_and_rrp</span><span class="p">,</span> <span class="n">halfhourly_data</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_region_price</span><span class="p">(</span><span class="n">date_region_prices</span><span class="p">,</span> <span class="n">regions</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd">    returns the dates and prices in two columns grouped by region,</span>
</span><span class='line'><span class="sd">    suitable for plotting with matplotlib.</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    the order of returned prices is the same order as the `regions`</span>
</span><span class='line'><span class="sd">    argument.</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    Args:</span>
</span><span class='line'><span class="sd">      date_region_prices: a list of (date, region, price) tuples</span>
</span><span class='line'><span class="sd">       [(datetime(2012, 08, 09), &quot;QLD1&quot;, 45.6),</span>
</span><span class='line'><span class="sd">        (datetime(2012, 08, 09, 1), &quot;NSW1&quot;, 46.0)</span>
</span><span class='line'><span class="sd">         ...</span>
</span><span class='line'><span class="sd">       ]</span>
</span><span class='line'><span class="sd">      regions: A list of the regions to return.</span>
</span><span class='line'><span class="sd">    &gt;&gt;&gt; get_region_price([(datetime(2012, 09, 09), &quot;QLD1&quot;, 43.2),</span>
</span><span class='line'><span class="sd">                          (datetime(2012, 09, 09), &quot;NSW1&quot;, 45.5),</span>
</span><span class='line'><span class="sd">                          (datetime(2012, 09, 10), &quot;NSW1&quot;, 44.2),</span>
</span><span class='line'><span class="sd">                          ...],</span>
</span><span class='line'><span class="sd">                          (&quot;NSW1&quot;, &quot;QLD1&quot;))</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    [(datetime(2012, 09, 09), datetime(2012, 09, 10))</span>
</span><span class='line'><span class="sd">     (45.5, 44.2)],</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    [(datetime(2012, 09, 09),)</span>
</span><span class='line'><span class="sd">     (43.2,)]</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    ...</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="n">region_prices</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
</span><span class='line'>    <span class="k">for</span> <span class="n">date</span><span class="p">,</span> <span class="n">region</span><span class="p">,</span> <span class="n">price</span> <span class="ow">in</span> <span class="n">date_region_prices</span><span class="p">:</span>
</span><span class='line'>        <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span>  <span class="o">+</span> <span class="s">&#39;d&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">date</span><span class="p">)</span>
</span><span class='line'>        <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span>  <span class="o">+</span> <span class="s">&#39;p&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">price</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">for</span> <span class="n">region</span> <span class="ow">in</span> <span class="n">regions</span><span class="p">:</span>
</span><span class='line'>        <span class="k">yield</span> <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span><span class="o">+</span><span class="s">&#39;d&#39;</span><span class="p">],</span> <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span><span class="o">+</span><span class="s">&#39;p&#39;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">figure</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="n">dates</span><span class="p">,</span> <span class="n">prices</span> <span class="ow">in</span> <span class="n">get_region_price</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span> <span class="n">REGIONS</span><span class="p">):</span>
</span><span class='line'>    <span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">dates</span><span class="p">,</span> <span class="n">prices</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">legend</span><span class="p">(</span><span class="n">REGIONS</span><span class="p">)</span>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">()</span>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s">&quot;Time of day&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s">&quot;Electricity Price A$/MWh&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">figure</span><span class="o">.</span><span class="n">autofmt_xdate</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<h4>Grouping the regions together</h4>

<p>I want to plot each of the five Australian regions&#8217;s prices as a separate
series. But I don&#8217;t have the data organised into separate x axis and y axis
values. Instead there is one long Python list that has <em>all</em> regions.</p>

<figure class='code'><figcaption><span>one long region list</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="p">[</span>
</span><span class='line'><span class="p">(</span><span class="s">&#39;2012-01-01 00:00&#39;</span><span class="p">,</span> <span class="s">&#39;NSW1&#39;</span><span class="p">,</span> <span class="mf">34.5</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s">&#39;2012-01-01 00:00&#39;</span><span class="p">,</span> <span class="s">&#39;VIC1&#39;</span><span class="p">,</span> <span class="mf">33.2</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s">&#39;2012-01-01 00:00&#39;</span><span class="p">,</span> <span class="s">&#39;SA1&#39;</span><span class="p">,</span>  <span class="mf">36.1</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s">&#39;2012-01-01 00:00&#39;</span><span class="p">,</span> <span class="s">&#39;TAS1&#39;</span><span class="p">,</span> <span class="mf">38.2</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s">&#39;2012-01-01 00:00&#39;</span><span class="p">,</span> <span class="s">&#39;QLD1&#39;</span><span class="p">,</span> <span class="mf">37.4</span><span class="p">),</span>
</span><span class='line'><span class="p">(</span><span class="s">&#39;2012-01-01 00:30&#39;</span><span class="p">,</span> <span class="s">&#39;NSW1&#39;</span><span class="p">,</span> <span class="mf">34.6</span><span class="p">),</span>
</span><span class='line'><span class="o">...</span>
</span><span class='line'><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here is a way to use <code>defaultdict</code> to collect the <code>date</code> and <code>price</code> per region.
For example the <code>'NSW1'</code> and <code>'VIC1'</code> regions. The <code>defaultdict</code>
<a href="http://docs.python.org/library/collections.html#collections.defaultdict">(official docs)</a>
is just like a normal dictionary, except that it has one additional powerful feature:</p>

<blockquote><p>`defaultdict` will auto-initialise a new value if you attempt to access a `key` that is missing.</p></blockquote>


<p>Confused? Here is a concrete example. Grouping power station names by
generator category (Nuclear, Wind,..) using a <em>normal</em> Python <code>dict</code>:</p>

<figure class='code'><figcaption><span>with a normal dict</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">gens</span> <span class="o">=</span> <span class="p">{}</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;NUCLEAR&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;NUCLEAR-1&#39;</span><span class="p">,</span> <span class="s">&#39;HILLVIEW-2&#39;</span><span class="p">,</span> <span class="s">&#39;NUCLEAR-2&#39;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="c"># we can add a new nuclear generator name.</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;NUCLEAR&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;HILLVIEW-1&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># we can&#39;t add a new wind farm name - yet.</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;WINDFARM&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;WINDY-HILL-1&#39;</span><span class="p">)</span>
</span><span class='line'><span class="c"># KeyError &#39;WINDFARM&#39;!</span>
</span><span class='line'>
</span><span class='line'><span class="c"># first must make a new empty wind farm list</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;WINDFARM&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
</span><span class='line'><span class="c"># now this works.</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;WINDFARM&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;WINDY-HILL-1&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>A <code>KeyError</code> exception will be raised on line 8, because <code>'WINDFARM'</code> is a key
that doesn&#8217;t exist in the <code>gens</code> dictionary yet. It isn&#8217;t until line 12 that
the <code>'WINDFARM'</code> key is entered into the dictionary and the first wind farm can
be appended.</p>

<p>Here is the same code using <code>defaultdict</code> to initialise an empty list when
there is a missing key. Notice that there is no need to create a key with
an empty list before appending.</p>

<figure class='code'><figcaption><span>with defaultdict</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>
</span><span class='line'>
</span><span class='line'><span class="n">gens</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># empty list created for &#39;NUCLEAR&#39; and straight away we extend it.</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;NUCLEAR&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="s">&#39;NUCLEAR-1&#39;</span><span class="p">,</span> <span class="s">&#39;HILLVIEW-2&#39;</span><span class="p">,</span> <span class="s">&#39;NUCLEAR-2&#39;</span><span class="p">])</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;NUCLEAR&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;HILLVIEW-1&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># empty list created for &#39;WINDFARM&#39; and straight away we append.</span>
</span><span class='line'><span class="n">gens</span><span class="p">[</span><span class="s">&#39;WINDFARM&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;WINDY-HILL-1&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Having seen <code>defaultdict</code> take another look at this code section from
<code>final.py</code>:</p>

<figure class='code'><figcaption><span>using default dict to group things</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">region_prices</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
</span><span class='line'><span class="k">for</span> <span class="n">date</span><span class="p">,</span> <span class="n">region</span><span class="p">,</span> <span class="n">price</span> <span class="ow">in</span> <span class="n">date_region_prices</span><span class="p">:</span>
</span><span class='line'>    <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span>  <span class="o">+</span> <span class="s">&#39;d&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">date</span><span class="p">)</span>
</span><span class='line'>    <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span>  <span class="o">+</span> <span class="s">&#39;p&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">price</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>It makes two lists for every region. The key to the first list <code>region + 'd'</code>
would look like <code>NSW1d</code> or <code>VIC1d</code>. The key to the second list is <code>region + 'p'</code>
and looks like <code>NSW1p</code> or <code>VIC1p</code>.</p>

<p>The <code>d</code> stands for date, our x axis and the <code>p</code> stands for price, our y axis.
Its time to plot those x and y values.</p>

<h4>Making your own iterator</h4>

<p>Use the <code>yield</code> keyword in a function to turn that function into something
that can be used in a <code>for</code>loop (an iterable).</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>    <span class="k">for</span> <span class="n">region</span> <span class="ow">in</span> <span class="n">regions</span><span class="p">:</span>
</span><span class='line'>        <span class="k">yield</span> <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span><span class="o">+</span><span class="s">&#39;d&#39;</span><span class="p">],</span> <span class="n">region_prices</span><span class="p">[</span><span class="n">region</span><span class="o">+</span><span class="s">&#39;p&#39;</span><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>I used the <code>yield</code> keyword in the <code>get_region_price</code> function to return the
<code>date</code> and <code>price</code> (x and y axis) pairs that were grouped using <code>defaultdict</code>.
They are returned one region at a time in the forloop.</p>

<figure class='code'><figcaption><span>using a function with yield</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">for</span> <span class="n">dates</span><span class="p">,</span> <span class="n">prices</span> <span class="ow">in</span> <span class="n">get_region_price</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span> <span class="n">REGIONS</span><span class="p">):</span>
</span><span class='line'>    <span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">dates</span><span class="p">,</span> <span class="n">prices</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>yield</code> will take some getting used to if you&#8217;ve never seen it before. Try
working with this script on your computer so you can see what is happening:</p>

<figure class='code'><figcaption><span>yield demo</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">names_age</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&quot;NUCLEAR1&quot;</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="p">(</span><span class="s">&quot;NUCLEAR2&quot;</span><span class="p">,</span> <span class="mi">11</span><span class="p">),</span> <span class="p">(</span><span class="s">&quot;WINDYPEAK&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">generator_names</span><span class="p">(</span><span class="n">names_age</span><span class="p">):</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">print</span> <span class="s">&#39;[generator_names] started the generator_names generator&#39;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">age</span> <span class="ow">in</span> <span class="n">names_age</span><span class="p">:</span>
</span><span class='line'>    <span class="k">print</span> <span class="s">&#39;[generator_names] about to yield&#39;</span><span class="p">,</span> <span class="n">name</span>
</span><span class='line'>    <span class="k">yield</span> <span class="n">name</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">generator_names</span><span class="p">(</span><span class="n">names_age</span><span class="p">):</span>
</span><span class='line'>  <span class="k">print</span> <span class="s">&#39;I got name: &#39;</span><span class="p">,</span> <span class="n">name</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>yield output</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="p">[</span><span class="n">generator_names</span><span class="p">]</span> <span class="n">started</span> <span class="n">the</span> <span class="n">generator_names</span> <span class="n">generator</span>
</span><span class='line'><span class="p">[</span><span class="n">generator_names</span><span class="p">]</span> <span class="n">about</span> <span class="n">to</span> <span class="k">yield</span> <span class="n">NUCLEAR1</span>
</span><span class='line'><span class="n">I</span> <span class="n">got</span> <span class="n">name</span><span class="p">:</span>  <span class="n">NUCLEAR1</span>
</span><span class='line'><span class="p">[</span><span class="n">generator_names</span><span class="p">]</span> <span class="n">about</span> <span class="n">to</span> <span class="k">yield</span> <span class="n">NUCLEAR2</span>
</span><span class='line'><span class="n">I</span> <span class="n">got</span> <span class="n">name</span><span class="p">:</span>  <span class="n">NUCLEAR2</span>
</span><span class='line'><span class="p">[</span><span class="n">generator_names</span><span class="p">]</span> <span class="n">about</span> <span class="n">to</span> <span class="k">yield</span> <span class="n">WINDYPEAK</span>
</span><span class='line'><span class="n">I</span> <span class="n">got</span> <span class="n">name</span><span class="p">:</span>  <span class="n">WINDYPEAK</span>
</span></code></pre></td></tr></table></div></figure>


<h4>Plotting professionally in only 8 lines of code</h4>

<p>Plotting the dates and prices is very easy once you have them in two lists, x
axis and y axis.</p>

<p>The plot commands are similar to Matlab plotting routines:</p>

<figure class='code'><figcaption><span>displaying a chart</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">figure</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="n">dates</span><span class="p">,</span> <span class="n">prices</span> <span class="ow">in</span> <span class="n">get_region_price</span><span class="p">(</span><span class="n">prices</span><span class="p">,</span> <span class="n">REGIONS</span><span class="p">):</span>
</span><span class='line'>    <span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">dates</span><span class="p">,</span> <span class="n">prices</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">legend</span><span class="p">(</span><span class="n">REGIONS</span><span class="p">)</span>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">grid</span><span class="p">()</span>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s">&quot;Time of day&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s">&quot;Electricity Price A$/MWh&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">figure</span><span class="o">.</span><span class="n">autofmt_xdate</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here is the list of steps in the code above.</p>

<ol>
<li>Create an empty figure;</li>
<li>Plot each region&#8217;s prices;</li>
<li>Display a legend;</li>
<li>Enable grid lines;</li>
<li>Set the x-axis label;</li>
<li>Set the y-axis label;</li>
<li>Auto-rotate the x axis date labels; and</li>
<li>Show the plot.</li>
</ol>


<h4>Conclusion</h4>

<p>The final program is quite short, just 100 lines of code. But it covers
such a wide range of tasks:</p>

<ul>
<li>Downloading files from the internet;</li>
<li>Unzipping files;</li>
<li>Reading CSV files;</li>
<li>Sorting, transposing and filtering data; and</li>
<li>Displaying data on a chart.</li>
</ul>


<p>The post may not be clear in certain areas, or you may want us to write about
something in more detail, so tell us using the form below.</p>

<div id="wufoo-m7x3w7">
Fill out my <a href="http://whitau.wufoo.com/forms/m7x3w7">online form</a>.
</div>


<script type="text/javascript">var m7x3w7;(function(d, t) {
var s = d.createElement(t), options = {
'userName':'whitau', 
'formHash':'m7x3w7', 
'autoResize':true,
'height':'437',
'async':true,
'header':'show'};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function() {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { m7x3w7 = new WufooForm();m7x3w7.initialize(options);m7x3w7.display(); } catch (e) {}};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[All you need to analyse the electricity market pt 3]]></title>
    <link href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-3/"/>
    <updated>2012-07-20T16:37:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-3</id>
    <content type="html"><![CDATA[<p>If you are an electrical engineer, and want to know how to use Python
to get data from the Internet and display it, this post is for you.</p>

<p>(This is the third part of a four part series. By the end we&#8217;ll have written a Python
script to display a chart of electricity market prices.
<a href="#register">Enter your email &rarr;</a> on the right so that you don&#8217;t miss the final post.)</p>

<ul>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">All you need to analyse the electricity market pt 1</a></li>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-2/">All you need to analyse the electricity market pt 2</a></li>
<li>All you need to analyse the electricity market pt 3</li>
<li><a href="http://www.whit.com.au/blog/2012/08/all-you-need-to-analyse-the-electricity-market-final/">All you need to analyse the electricity market final</a></li>
</ul>


<h4>Australian electricity prices are high - let&#8217;s analyse</h4>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" width="300" title="Australian Electricity Prices are higher since the introduction of the carbon tax" >
</td></tr><tr><td style="text-align: center; width: 300px;">Very high electricity prices <a href="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" title="Larger View">[Larger Size]</a> </td></tr></tbody></table>


<p><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">Previously</a> I
mentioned that the Australian electricity prices have gone through the roof
(more than doubling) since the introduction of the carbon tax.</p>

<p>This series of posts is exploring how to analyse market data accessible from the
internet. The methods described can be adapted to your country&#8217;s data or any
sort of data available on the internet.</p>

<p>We began the series with a post detailing how to obtain a CSV file that
contains the latest electricity market prices.</p>

<p><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-2/">Then</a> we
unzipped the price data CSV file that was downloaded in Part 1 and had a brief
look at its contents.</p>

<p>Now we will teach you how to pull that CSV file apart using Python. You will
master the ability to highlight the columns and rows that you are interested
in. Just like top Japanese chefs are qualified to cut the good meat from the
<a href="http://en.wikipedia.org/wiki/Fugu">fugu fish</a>, you too will learn to slice the
good data from the CSV file.</p>

<p>The code we have developed over this series so far:</p>

<ol>
<li>downloads a zipped file;</li>
<li>unzips it; and</li>
<li>reads the file contents as a CSV.</li>
</ol>


<figure class='code'><figcaption><span>extractziptocsv.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># assuming there is only one CSV in the zipped file.</span>
</span><span class='line'><span class="n">csv_filename</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_file</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">prices_csv_file</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The example CSV file downloaded earlier had over 30 columns of information and
many thousands of rows. We&#8217;ll use Python to get exactly the columns and rows
that we want.</p>

<p><em>Which rows are important?</em> Knowing what is in the CSV file is paramount at
this stage. To this end, the site that provides the data may also provide a
specification of the file structure. Failing that, you may have to get intimate
with the data and spend a bit of time working out the format for yourself.</p>

<p>For the data provided by the Australian electricity market operator, the first
CSV column is a label. Each label describes the purpose of that row. There are
three values, <code>C</code>, <code>I</code> or <code>D</code>. Shown below is an example of the data stored
in the first column,</p>

<figure class='code'><figcaption><span>CSV file structure</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">C</span><span class="p">,</span>
</span><span class='line'><span class="n">I</span><span class="p">,</span>
</span><span class='line'><span class="n">D</span><span class="p">,</span>
</span><span class='line'><span class="n">D</span><span class="p">,</span>
</span><span class='line'><span class="n">D</span><span class="p">,</span>
</span><span class='line'><span class="n">D</span><span class="p">,</span>
</span><span class='line'><span class="n">I</span><span class="p">,</span>
</span><span class='line'><span class="n">D</span><span class="p">,</span>
</span><span class='line'><span class="n">D</span><span class="p">,</span>
</span><span class='line'><span class="n">I</span><span class="p">,</span>
</span><span class='line'><span class="o">...</span>
</span></code></pre></td></tr></table></div></figure>


<p>Rows marked with a <code>C</code> are comment rows, they give further information about
the file itself but aren&#8217;t necessary for us to worry about.</p>

<p>Rows marked with an <code>I</code> are header rows. The header row is just like a header
row you use in a normal Microsoft Excel spreadsheet, it indicates what data is
stored in that column.  For our goal of finding the price of electricity in
different regions of Australia over time, the columns that we are looking for
are <code>SETTLEMENTDATE</code> (date and time), <code>REGIONID</code> (price region) and <code>RRP</code>
(electricity price $/MWh).</p>

<p>Rows marked with a <code>D</code> are the data rows. We&#8217;ll take these rows for the
<code>SETTLEMENTDATE</code>, <code>REGIONID</code> and <code>RRP</code> then plot them on a chart.</p>

<h4>Multiple header rows in a CSV file?</h4>

<p>Immediately though, we run into a problem. Notice in the <code>CSV file structure</code>
figure shown above that there are multiple <code>I</code> header rows? There are no less
than four in the CSV file we downloaded. You can think of it as four CSV files
crammed into a single file.</p>

<p>We are only interested in one of these four sections, the section with the
columns we mentioned before, <code>SETTLEMENTDATE</code>, <code>REGIONID</code> and <code>RRP</code>. Through
analysis of the file structure, we know that all the data rows we are
interested in all begin with:</p>

<figure class='code'><figcaption><span>example D data row</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">D</span><span class="p">,</span><span class="n">TREGION</span><span class="p">,,</span><span class="mi">1</span>
</span></code></pre></td></tr></table></div></figure>


<h4>Master technique one: <code>filter</code></h4>

<p>Here is how to update the program to print the rows beginning with <code>D,TREGION,,1</code>:</p>

<figure class='code'><figcaption><span>takedatarows.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># assuming there is only one CSV in the zipped file.</span>
</span><span class='line'><span class="n">csv_filename</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_file</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">prices_csv_file</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">is_halfhourly_data</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;Returns True if the given row starts with &#39;D&#39;, &#39;TREGION&#39;, &#39;&#39;, &#39;1&#39;&quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">row</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="s">&quot;D&quot;</span><span class="p">,</span> <span class="s">&quot;TREGION&quot;</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">,</span> <span class="s">&quot;1&quot;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span> <span class="nb">filter</span><span class="p">(</span><span class="n">is_halfhourly_data</span><span class="p">,</span> <span class="n">prices_csv_reader</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>filter</code> function will only return the rows for which the function
<code>is_halfhourly_data</code> returns <code>True</code>.</p>

<h4>Master technique 2: <code>map</code></h4>

<p>Having correctly isolated the rows that interest us, slice up those
columns and get the <code>SETTLEMENTDATE</code>, <code>REGIONID</code> and <code>RRP</code> columns (column
numbers <code>4</code>, <code>6</code> and <code>7</code>).</p>

<figure class='code'><figcaption><span>takedatarows.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># assuming there is only one CSV in the zipped file.</span>
</span><span class='line'><span class="n">csv_filename</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_file</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">prices_csv_file</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">is_halfhourly_data</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;Returns True if the given row starts with &#39;D&#39;, &#39;TREGION&#39;, &#39;&#39;, &#39;1&#39;&quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">row</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="s">&quot;D&quot;</span><span class="p">,</span> <span class="s">&quot;TREGION&quot;</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">,</span> <span class="s">&quot;1&quot;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">halfhourly_data</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="n">is_halfhourly_data</span><span class="p">,</span> <span class="n">prices_csv_reader</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_date_region_and_rrp</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">])</span>
</span><span class='line'>
</span><span class='line'><span class="n">date_region_price</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">get_date_region_and_rrp</span><span class="p">,</span> <span class="n">halfhourly_data</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>map</code> function will return a list of the result of
<code>get_date_region_and_rrp</code> called with each row in <code>halfhourly_data</code> as an argument.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">get_date_region_and_rrp</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">])</span>
</span><span class='line'>
</span><span class='line'><span class="n">date_region_price</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">get_date_region_and_rrp</span><span class="p">,</span> <span class="n">halfhourly_data</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The above section of code using <code>map</code> is the equivalent of this code using
<code>for</code> loop.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">get_date_region_and_rrp</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">])</span>
</span><span class='line'>
</span><span class='line'><span class="n">date_region_price</span> <span class="o">=</span> <span class="p">[]</span>
</span><span class='line'>
</span><span class='line'><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">halfhourly_data</span><span class="p">:</span>
</span><span class='line'>    <span class="n">new_row</span> <span class="o">=</span> <span class="n">get_date_region_and_rrp</span><span class="p">(</span><span class="n">row</span><span class="p">)</span>
</span><span class='line'>    <span class="n">date_region_price</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">new_row</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>map</code> is an extremely versatile function. Those four lines of <code>for</code> loop code
are replaced with one <code>map</code> line of code.</p>

<h4>And now only the good data remains</h4>

<p>The <code>date_region_price</code> variable will have these contents:</p>

<figure class='code'><figcaption><span>date_region_price output</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="p">[[</span><span class="s">&quot;2012/04/02 10:30:00&quot;</span><span class="p">,</span> <span class="s">&quot;NSW1&quot;</span><span class="p">,</span> <span class="s">&quot;34.40&quot;</span><span class="p">],</span>
</span><span class='line'> <span class="p">[</span><span class="s">&quot;2012/04/02 10:30:00&quot;</span><span class="p">,</span> <span class="s">&quot;QLD1&quot;</span><span class="p">,</span> <span class="s">&quot;34.67&quot;</span><span class="p">],</span>
</span><span class='line'> <span class="p">[</span><span class="s">&quot;2012/04/02 10:30:00&quot;</span><span class="p">,</span> <span class="s">&quot;VIC1&quot;</span><span class="p">,</span> <span class="s">&quot;35.83&quot;</span><span class="p">],</span>
</span><span class='line'> <span class="o">...</span>
</span><span class='line'><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Only the columns that we are interested in. Nice work!</p>

<p>However there is still a small problem. All of the data values are still text.
Update the <code>get_date_region_and_rrp</code> to convert the first column to a date,
keep the second as a string and the third to a floating point value.</p>

<figure class='code'><figcaption><span>converted_data.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">datetime</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># assuming there is only one CSV in the zipped file.</span>
</span><span class='line'><span class="n">csv_filename</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_file</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">prices_csv_file</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">is_halfhourly_data</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;Returns True if the given row starts with &#39;D&#39;, &#39;TREGION&#39;, &#39;&#39;, &#39;1&#39;&quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">row</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="s">&quot;D&quot;</span><span class="p">,</span> <span class="s">&quot;TREGION&quot;</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">,</span> <span class="s">&quot;1&quot;</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">halfhourly_data</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="n">is_halfhourly_data</span><span class="p">,</span> <span class="n">prices_csv_reader</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_date_region_and_rrp</span><span class="p">(</span><span class="n">row</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd">    Returns the SETTLEMENTDATE, REGION and RRP from the given</span>
</span><span class='line'><span class="sd">    PUBLIC_PRICES CSV data row.</span>
</span><span class='line'>
</span><span class='line'><span class="sd">    SETTLEMENTDATE is converted to a Python date (the time is discarded);</span>
</span><span class='line'><span class="sd">    REGION is left as a string; and</span>
</span><span class='line'><span class="sd">    RRP is converted to a floating point.</span>
</span><span class='line'><span class="sd">    &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="s">&#39;%Y/%m/</span><span class="si">%d</span><span class="s"> %H:%M:%S&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">date</span><span class="p">(),</span>
</span><span class='line'>            <span class="n">row</span><span class="p">[</span><span class="mi">6</span><span class="p">],</span>
</span><span class='line'>            <span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="mi">7</span><span class="p">]))</span>
</span><span class='line'>
</span><span class='line'><span class="n">date_region_price</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">get_date_region_and_rrp</span><span class="p">,</span> <span class="n">halfhourly_data</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Great, now our data is in a format that Python can understand and plot. This is
what is contained in the <code>date_region_price</code> value now:</p>

<figure class='code'><figcaption><span>date_region_price converted output</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="p">[[</span><span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">2012</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="s">&quot;NSW1&quot;</span><span class="p">,</span> <span class="mf">34.40</span><span class="p">],</span>
</span><span class='line'> <span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">2012</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="s">&quot;QLD1&quot;</span><span class="p">,</span> <span class="mf">34.67</span><span class="p">],</span>
</span><span class='line'> <span class="p">[</span><span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">2012</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="s">&quot;VIC1&quot;</span><span class="p">,</span> <span class="mf">35.83</span><span class="p">],</span>
</span><span class='line'> <span class="o">...</span>
</span><span class='line'><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Perfect. We now have all the data formatted exactly the way we want it.</p>

<h4>Conclusion</h4>

<p>We&#8217;ve used <code>filter</code> and <code>map</code> to quickly and efficiently sort and slice the
CSV data. Just like a master Japanese chef, I&#8217;m sure that you will not poison
your patrons with bad slices of data. <code>filter</code> and <code>map</code> are advanced level
functions that are often used to replace <code>for</code> loops. Please practice using
<code>map</code> and <code>filter</code>. Experiment with them so that you understand how they work!</p>

<p>In the next, and final, blog post of this series we&#8217;ll show you how to plot
the results using <strong>matplotlib</strong>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Why was there a blackout in Alberta?]]></title>
    <link href="http://www.whit.com.au/blog/2012/07/why-was-there-blackouts-in-alberta/"/>
    <updated>2012-07-11T12:32:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/07/why-was-there-blackouts-in-alberta</id>
    <content type="html"><![CDATA[<p>Just what went wrong yesterday in Alberta to cause rolling blackouts and electricity prices that were 50 times higher than normal?</p>

<!--more-->




<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
    <img src="http://www.whit.com.au/blog/images/blog/alberta.png" width="500">
</td></tr><tr><td style="text-align: center; width: 500px;">The AESO manages the system with multiple generators unavailable <a href="http://www.whit.com.au/blog/images/blog/alberta.png">[Larger Size]</a></td></tr></tbody></table>


<p>Alberta, Canada was hit by
<a href="http://www.cbc.ca/news/canada/edmonton/story/2012/07/09/edmonton-rolling-blackouts-power.html">rolling blackouts yesterday</a> (9th July 2012)
as the state sweltered through a heatwave that sent temperatures
north of 30 degrees celcius.</p>

<p>The unexpected loss of power had some
<a href="http://www.cbc.ca/news/canada/edmonton/story/2012/07/10/calgary-electrical-blackout-folo-reaction.html">calling for an investigation</a>
into excessive use of market power.</p>

<h4>How did the blackouts occur?</h4>

<p>The AESO did not have enough available generation to <em>securely meet the demand</em>
for electricity, so it switched off the power to some houses and businesses
across the state until it could securely meet the demand.</p>

<h4>Securely meet the demand</h4>

<p><span class='pullquote-right' data-pullquote='What is the worst thing that can happen next?'>
I&#8217;ll explain what I mean by <em>securely meet the demand</em>. The AESO is constantly
asking the question: What is the worst thing that can happen next? There
is always a list of things that could go wrong. And that list is as long as
your arm:</p>

<p></span></p>

<ul>
<li>A generator could suddenly shut down without notice;</li>
<li>A main powerline could fail and be unable to transport power;</li>
<li>A major circuit breaker (a big power switch) could stop functioning;</li>
<li>and more..</li>
</ul>


<p>Securely operating the system means that, yes we are ok now, but we&#8217;ll still
be ok even if <em>one more</em> thing goes wrong.</p>

<p>One of the tests that the AESO use to determine if they are <em>secure</em> is to
ask: How much additional generating capacity do I have up my sleeve?</p>

<p>If the answer is &#8220;less than 500 MW&#8221; (about the size of one large gas power
station) then they are <em>not secure</em>. They are in the danger zone, and if one
more bad thing happens while they are in the danger zone, the entire power
system could collapse. Restoring from a system collapse can take days.</p>

<h4>So what happened yesterday?</h4>

<p>Looking at the chart above, we can see that three additional generators
went out of service at 1300 hrs. On the temperature chart darker
red colours mean more generators simultaneously out of service.</p>

<p>It was then that the AESO declared Energy Emergency Alert 1 (shown on the
demand chart. Darker colours mean a more severe alert level). This means, I
still have about 500 MW, I hope nothing else bad happens, because we could go
under 500 MW.</p>

<p>Soon after Alert 1 was sounded, one generator came back online, but then
another two went offline. One step forward and two steps back.</p>

<p>This was enough to sound Energy Emergency Alert 2 and Alert 3 at almost the
same time.</p>

<p>At Alert 2, customers that have previously agreed to help out by reducing
their demand do so. And at Alert 3 there is no choice but to shut down entire
suburbs at a time. Desparately clawing for a 500 MW buffer.</p>

<h4>So AESO had no choice but to switch off load</h4>

<p><span class='pullquote-right' data-pullquote='Those generator owners
were earning a lot of money. C$ 57 million - for 6 hours work.'>
But isn&#8217;t it strange that so many generators went offline at once? The price
for electricity increased by 5000% (50 times higher). Those generator owners
were earning a lot of money. C$ 57 million - for 6 hours work.
</span></p>

<p>While the natural response is to call these generators out for being so
greedy, take a look at the temperatures (for Edmonton). They are only a few
degrees below the highest ever recorded temperatures. Most power equipment is
only designed to withstand a certain temperature range. Operating outside of
that range can damage the equipment.</p>

<p>A similar situation happened in Tasmania in 2009. The high voltage line
connecting it and the mainland was not designed to cope with temperatures
above 35 degrees. The shutdown of that cable, and other coincident shutdowns
meant widespread rolling blackouts and 20,000 customers without power.</p>

<p>We&#8217;ll watch this case carefully, the AESO have already committed to a review
but not to releasing the results (unlike the Australian Energy Market Operator
that publicly releases investigations). Let&#8217;s hope that any lessons are
learned and quickly implemented so that we do not see a repeat this summer.</p>

<p><em>Are you an engineer or market analyst?</em> We&#8217;re running a blog series that
teaches you everything you need to know about analysing the electricity market
<a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">read it here</a>.
<a href="#register">Register your email on the right &rarr;</a> so you don&#8217;t miss any blog updates.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[All you need to analyse the electricity market pt 2]]></title>
    <link href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-2/"/>
    <updated>2012-07-06T13:05:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-2</id>
    <content type="html"><![CDATA[<p>If you are an electrical engineer, and want to know how to use Python
to get data from the internet and display it, this post is for you.</p>

<p>(This is the second part of a series. By the end we&#8217;ll have written a Python
script to display a chart of electricity market prices.</p>

<ul>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">All you need to analyse the electricity market pt 1</a></li>
<li>All you need to analyse the electricity market pt 2</li>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-3/">All you need to analyse the electricity market pt 3</a></li>
<li><a href="http://www.whit.com.au/blog/2012/08/all-you-need-to-analyse-the-electricity-market-final/">All you need to analyse the electricity market final</a></li>
</ul>


<h4>Australian electricity prices are high - let&#8217;s analyse</h4>

<p><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">Previously</a> I
mentioned that the electricity prices have gone through the roof (more than
doubled) post introduction of the carbon tax in Australia.</p>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" width="300" title="Australian Electricity Prices are higher since the introduction of the carbon tax" >
</td></tr><tr><td style="text-align: center; width: 300px;">Very high electricity prices <a href="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" title="Larger View">[Larger Size]</a> </td></tr></tbody></table>


<p>We&#8217;re using these high prices as an excuse to learn how to download and
display price data from the internet. This code will work wherever you are in
the world.</p>

<h4>Using Python to extract a zipped file</h4>

<p>Last time, we downloaded a zipped file filled with electricity prices from the
energy market operator&#8217;s website (<a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/">read about it here</a> if you want to catch up). Here is the final code from that post:</p>

<!--more-->




<figure class='code'><figcaption><span>downloadzip.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;PUBLIC_PRICES.ZIP&#39;</span><span class="p">,</span> <span class="s">&#39;wb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">pricesfile</span><span class="p">:</span>
</span><span class='line'>  <span class="n">pricesfile</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">zippedfile</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span></code></pre></td></tr></table></div></figure>


<p>In this post we are going to open a zip file containing CSV files and read the
data contained within. To begin, we open the zipped file and get a list of the
file names inside it.  We&#8217;ve used Python&#8217;s <code>zipfile</code> module and its <code>ZipFile</code>
class to turn the zip file we downloaded into something that we can use.</p>

<p>A listing of all the filenames in the zip file can be produced using the <code>namelist()</code> method.</p>

<figure class='code'><figcaption><span>extractzip.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'><span class="n">filenames</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span> <span class="n">filenames</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>output of &#8216;print filenames&#8217;</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="c"># just one CSV file inside this zipped file.</span>
</span><span class='line'><span class="p">[</span><span class="s">&#39;PUBLIC_PRICES_201207040000_20120705040607.CSV&#39;</span><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>There was just one CSV file inside the zipped file we just opened. We will now
add some code to open it and convert it to Python lists using the <code>csv</code>
module included with Python. <a href="http://www.whit.com.au/blog/2011/11/reading-and-writing-csv-files/">Here is a quick refresh on the CSV module</a>.</p>

<figure class='code'><figcaption><span>extractziptocsv.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">zipfile</span> <span class="kn">import</span> <span class="n">ZipFile</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># zippedfile is now one long string.</span>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="c"># StringIO turns the string into a real file-like object.</span>
</span><span class='line'><span class="n">opened_zipfile</span> <span class="o">=</span> <span class="n">ZipFile</span><span class="p">(</span><span class="n">StringIO</span><span class="p">(</span><span class="n">zippedfile</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="c"># assuming there is only one CSV in the zipped file.</span>
</span><span class='line'><span class="n">csv_filename</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">namelist</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_file</span> <span class="o">=</span> <span class="n">opened_zipfile</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">prices_csv_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">prices_csv_file</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>csv.reader</code> creates an object that has special functions to effortlessly
return the CSV price data as Python lists. Printing the object,
<code>print prices_csv_reader</code>, shows how the <code>csv</code> module has read in the file:</p>

<figure class='code'><figcaption><span>output of print &#8216;prices_csv_reader&#8217;</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="p">[[</span><span class="s">&#39;C&#39;</span><span class="p">,</span> <span class="s">&#39;NEMP.WORLD&#39;</span><span class="p">,</span> <span class="s">&#39;PRICES&#39;</span><span class="p">,</span> <span class="s">&#39;AEMO&#39;</span><span class="p">,</span>  <span class="o">...</span><span class="p">]</span>
</span><span class='line'> <span class="p">[</span><span class="s">&#39;I&#39;</span><span class="p">,</span> <span class="s">&#39;DREGION&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="s">&#39;2&#39;</span><span class="p">,</span> <span class="s">&#39;SETTLEMENTDATE&#39;</span><span class="p">,</span> <span class="s">&#39;RUNNO&#39;</span><span class="p">,</span> <span class="s">&#39;REGIONID&#39;</span><span class="p">,</span> <span class="o">...</span><span class="p">]</span>
</span><span class='line'>  <span class="o">...</span>
</span><span class='line'><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Look carefully at that output, notice how <code>csv.reader</code> has detected all the
commas and correctly separated all of the columns and rows. All the data is
stored in a list of rows. Now that we have the data in this form, extracting
useful data from this structure can be achieved using the usual Python
techniques.</p>

<p>In the first two posts of this series, we&#8217;ve:</p>

<ol>
<li>downloaded a zipped file using <code>urllib2</code>;</li>
<li>unzipped the file to get the CSV using <code>zipfile</code>;</li>
<li>got ready to read the csv file contents using <code>csv</code>.</li>
</ol>


<p>In the next blog post we&#8217;ll take a closer look at the CSV file using Python.
In particular, we will manipulate the CSV file to extract only the data that is
of interest to us.</p>

<p>If you want to be emailed when the next blog is ready, just enter your email
<a href="#register">up the top &rarr;</a>. We&#8217;ll only email you when a new blog is ready
and with tips on becoming an advanced Python using power systems engineer.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[All you need to analyse the electricity market]]></title>
    <link href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market/"/>
    <updated>2012-07-04T17:19:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market</id>
    <content type="html"><![CDATA[<p>If you are an electrical engineer, and want to know how to use Python
to get data from the internet and display it, this post is for you.</p>

<p>(This is the first part of a series. By the end we&#8217;ll have written a Python
script to display a chart of electricity market prices.</p>

<ul>
<li>All you need to analyse the electricity market pt 1</li>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-2/">All you need to analyse the electricity market pt 2</a></li>
<li><a href="http://www.whit.com.au/blog/2012/07/all-you-need-to-analyse-the-electricity-market-pt-3/">All you need to analyse the electricity market pt 3</a></li>
<li><a href="http://www.whit.com.au/blog/2012/08/all-you-need-to-analyse-the-electricity-market-final/">All you need to analyse the electricity market final</a></li>
</ul>


<h4>Electricity prices in Australia have gone bananas</h4>

<p>Since the carbon tax was introduced in Australia, the spot price for
electricity has been very high. From <strong>$22</strong> / MWh last month to over <strong>$50</strong>
/ MWh so far (see the chart below). Whether this is a long term change, or
just a temporary reaction, we don&#8217;t know. Instead of considering the
complexities of market forces, we&#8217;re going to show you step by step exactly
how to build your own Python program to display electricity prices, using
Australia as an example.</p>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" width="300" title="Australian Electricity Prices are higher since the introduction of the carbon tax" >
</td></tr><tr><td style="text-align: center; width: 300px;">Very high electricity prices <a href="https://lh6.googleusercontent.com/-8nuxe7RBgb0/T_Wq1vMgk_I/AAAAAAAAANY/mcuLAkEoQPU/s680/electricity-prices-australia.png" title="Larger View">[Larger Size]</a> </td></tr></tbody></table>


<p><em>Feel free to take the code, and configure it for your own country&#8217;s system.</em></p>

<h4>Downloading a zip file.</h4>

<p>Australia&#8217;s electricity market operator (AEMO) keeps all of the market data online
at <a href="http://www.nemweb.com.au/Reports/">http://www.nemweb.com.au/Reports/</a>.
The webpages are written in simple to understand HTML and link to zipped CSV files.</p>

<p>We&#8217;ll use Python to write a simple script that downloads a zipped file.</p>

<figure class='code'><figcaption><span>downloadzip.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">urllib2</span> <span class="kn">import</span> <span class="n">urlopen</span>
</span><span class='line'>
</span><span class='line'><span class="n">PRICE_REPORTS_URL</span> <span class="o">=</span> <span class="s">&#39;http://www.nemweb.com.au/Reports/CURRENT/Public_Prices&#39;</span>
</span><span class='line'><span class="n">ZIP_URL</span> <span class="o">=</span> <span class="s">&#39;/PUBLIC_PRICES_201207040000_20120705040607.ZIP&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="n">zippedfile</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">PRICE_REPORTS_URL</span> <span class="o">+</span> <span class="n">ZIP_URL</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;PUBLIC_PRICES.ZIP&#39;</span><span class="p">,</span> <span class="s">&#39;wb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">pricesfile</span><span class="p">:</span>
</span><span class='line'>  <span class="n">pricesfile</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">zippedfile</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span></code></pre></td></tr></table></div></figure>


<p>You may find that the link is expired, so you&#8217;ll get an error like this:</p>

<figure class='code'><figcaption><span>error</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>  <span class="n">File</span> <span class="s">&quot;/usr/lib/python2.7/urllib2.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">126</span><span class="p">,</span> <span class="ow">in</span> <span class="n">urlopen</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">_opener</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">timeout</span><span class="p">)</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;/usr/lib/python2.7/urllib2.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">406</span><span class="p">,</span> <span class="ow">in</span> <span class="nb">open</span>
</span><span class='line'>    <span class="n">response</span> <span class="o">=</span> <span class="n">meth</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;/usr/lib/python2.7/urllib2.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">519</span><span class="p">,</span> <span class="ow">in</span> <span class="n">http_response</span>
</span><span class='line'>    <span class="s">&#39;http&#39;</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">,</span> <span class="n">code</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="n">hdrs</span><span class="p">)</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;/usr/lib/python2.7/urllib2.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">444</span><span class="p">,</span> <span class="ow">in</span> <span class="n">error</span>
</span><span class='line'>    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_call_chain</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;/usr/lib/python2.7/urllib2.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">378</span><span class="p">,</span> <span class="ow">in</span> <span class="n">_call_chain</span>
</span><span class='line'>    <span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;/usr/lib/python2.7/urllib2.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">527</span><span class="p">,</span> <span class="ow">in</span> <span class="n">http_error_default</span>
</span><span class='line'>    <span class="k">raise</span> <span class="n">HTTPError</span><span class="p">(</span><span class="n">req</span><span class="o">.</span><span class="n">get_full_url</span><span class="p">(),</span> <span class="n">code</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="n">hdrs</span><span class="p">,</span> <span class="n">fp</span><span class="p">)</span>
</span><span class='line'><span class="n">urllib2</span><span class="o">.</span><span class="n">HTTPError</span><span class="p">:</span> <span class="n">HTTP</span> <span class="n">Error</span> <span class="mi">404</span><span class="p">:</span> <span class="n">Not</span> <span class="n">Found</span>
</span></code></pre></td></tr></table></div></figure>


<p><em>Got the error above?</em> Change <code>ZIP_URL</code> to match the url of a zip you can find on this
<a href="http://www.nemweb.com.au/Reports/CURRENT/Public_Prices">http://www.nemweb.com.au/Reports/CURRENT/Public_Prices</a>
page.</p>

<p>Unzip the downloaded file (the file is named <code>PUBLIC_PRICES.ZIP</code>) and look at
the CSV file inside. You will find something like this:</p>

<figure class='code'><figcaption><span>PUBLIC_PRICES.ZIP</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='text'><span class='line'>C,NEMP.WORLD,PRICES,AEMO,PUBLIC,2012/04/02,04:06:14,0000000235749444,,0000000235749438
</span><span class='line'>I,DREGION,,2,SETTLEMENTDATE,RUNNO,REGIONID,INTERVENTION,RRP,EEP,ROP,APCFLAG,MARKETSUSPENDEDFLAG,TOTALDEMAND,DEMANDFORECAST,DISPATCHABLEGENERATION,DISPATCHABLELOAD,NETINTERCHANGE,EXCESSGENERATION,LOWER5MINDISPATCH,LOWER5MINIMPORT,LOWER5MINLOCALDISPATCH,LOWER5MINLOCALPRICE,LOWER5MINLOCALREQ,LOWER5MINPRICE,LOWER5MINREQ,LOWER5MINSUPPLYPRICE,LOWER60SECDISPATCH,LOWER60SECIMPORT,LOWER60SECLOCALDISPATCH,LOWER60SECLOCALPRICE,LOWER60SECLOCALREQ,LOWER60SECPRICE,LOWER60SECREQ,LOWER60SECSUPPLYPRICE,LOWER6SECDISPATCH,LOWER6SECIMPORT,LOWER6SECLOCALDISPATCH,LOWER6SECLOCALPRICE,LOWER6SECLOCALREQ,LOWER6SECPRICE,LOWER6SECREQ,LOWER6SECSUPPLYPRICE,RAISE5MINDISPATCH,RAISE5MINIMPORT,RAISE5MINLOCALDISPATCH,RAISE5MINLOCALPRICE,RAISE5MINLOCALREQ,RAISE5MINPRICE,RAISE5MINREQ,RAISE5MINSUPPLYPRICE,RAISE60SECDISPATCH,RAISE60SECIMPORT,RAISE60SECLOCALDISPATCH,RAISE60SECLOCALPRICE,RAISE60SECLOCALREQ,RAISE60SECPRICE,RAISE60SECREQ,RAISE60SECSUPPLYPRICE,RAISE6SECDISPATCH,RAISE6SECIMPORT,RAISE6SECLOCALDISPATCH,RAISE6SECLOCALPRICE,RAISE6SECLOCALREQ,RAISE6SECPRICE,RAISE6SECREQ,RAISE6SECSUPPLYPRICE,AGGREGATEDISPATCHERROR,AVAILABLEGENERATION,AVAILABLELOAD,INITIALSUPPLY,CLEAREDSUPPLY,LOWERREGIMPORT,LOWERREGLOCALDISPATCH,LOWERREGLOCALREQ,LOWERREGREQ,RAISEREGIMPORT,RAISEREGLOCALDISPATCH,RAISEREGLOCALREQ,RAISEREGREQ,RAISE5MINLOCALVIOLATION,RAISEREGLOCALVIOLATION,RAISE60SECLOCALVIOLATION,RAISE6SECLOCALVIOLATION,LOWER5MINLOCALVIOLATION,LOWERREGLOCALVIOLATION,LOWER60SECLOCALVIOLATION,LOWER6SECLOCALVIOLATION,RAISE5MINVIOLATION,RAISEREGVIOLATION,RAISE60SECVIOLATION,RAISE6SECVIOLATION,LOWER5MINVIOLATION,LOWERREGVIOLATION,LOWER60SECVIOLATION,LOWER6SECVIOLATION,RAISE6SECRRP,RAISE6SECROP,RAISE6SECAPCFLAG,RAISE60SECRRP,RAISE60SECROP,RAISE60SECAPCFLAG,RAISE5MINRRP,RAISE5MINROP,RAISE5MINAPCFLAG,RAISEREGRRP,RAISEREGROP,RAISEREGAPCFLAG,LOWER6SECRRP,LOWER6SECROP,LOWER6SECAPCFLAG,LOWER60SECRRP,LOWER60SECROP,LOWER60SECAPCFLAG,LOWER5MINRRP,LOWER5MINROP,LOWER5MINAPCFLAG,LOWERREGRRP,LOWERREGROP,LOWERREGAPCFLAG
</span><span class='line'>D,DREGION,,2,&quot;2012/04/01 04:05:00&quot;,1,NSW1,0,24.01213,0,24.01213,0,,5880.16,1.20264,4358.97,0,-1521.19,0,,,100.55,,,,,,,,109.7,,,,,,,,34.35,,,,,,,,206,,,,,,,,94.27,,,,,,,,116.69,,,,,,0,10832.745,0,5907.18945,5912.38,,50,,,,38,,,,,,,,,,,,,,,,,,,0.96,0.96,0,0.39,0.39,0,0.85,0.85,0,1.35,1.35,0,0.5,0.5,0,1.5,1.5,0,3.85809,3.85809,0,6.222,6.222,0
</span><span class='line'>D,DREGION,,2,&quot;2012/04/01 04:05:00&quot;,1,QLD1,0,21.55498,0,21.55498,0,,4423.12,-0.58301,5327.25,0,904.13,0,,,13,,,,,,,,42.65,,,,,,,,40,,,,,,,,83,,,,,,,,82,,,,,,,,62,,,,,,0,10258,0,4442.88184,4441.41,,34,,,,76.44,,,,,,,,,,,,,,,,,,,0.96,0.96,0,0.39,0.39,0,0.85,0.85,0,1.35,1.35,0,0.5,0.5,0,1.5,1.5,0,3.85809,3.85809,0,6.222,6.222,0
</span><span class='line'>D,DREGION,,2,&quot;2012/04/01 04:05:00&quot;,1,SA1,0,22.2124,0,22.2124,0,,1144.89,-1.98004,1085.43,0,-59.46,0,,,0,,,,,,,,2,,,,,,,,2,,,,,,,,0,,,,,,,,30,,,,,,,,40.4,,,,,,4.93256,2768.82735,0,1141.90503,1144.93,,16,,,,0,,,,,,,,,,,,,,,,,,,0.96,0.96,0,0.39,0.39,0,0.85,0.85,0,1.35,1.35,0,0.5,0.5,0,1.5,1.5,0,3.85809,3.85809,0,6.222,6.222,0
</span><span class='line'>D,DREGION,,2,&quot;2012/04/01 04:05:00&quot;,1,TAS1,0,30.8637,0,30.8637,0,,896.9,3.52316,469.4,0,-427.5,0,,,47.74,,,,,,,,0,,,,,,,,13.59,,,,,,,,80.29,,,,,,,,73.59,,,,,,,,48.77,,,,,,-0.61674,2000,0,893.98877,896.9,,0,,,,6.53,,,,,,,,,,,,,,,,,,,1.1,1.1,0,0.9,0.9,0,2.3,2.3,0,2.8,2.8,0,0.1,0.1,0,0,0,0,0.1,0.1,0,2.46391,2.46391,0
</span><span class='line'>D,DREGION,,2,&quot;2012/04/01 04:05:00&quot;,1,VIC1,0,21.7,0,21.7,0,,4094.7,-22.9043,5268.16,0,1173.46,0,,,46,,,,,,,,40,,,,,,,,40,,,,,,,,11,,,,,,,,33,,,,,,,,45,,,,,,0,8780,0,4134.81494,4113.61,,20,,,,9.03,,,,,,,,,,,,,,,,,,,0.96,0.96,0,0.39,0.39,0,0.85,0.85,0,1.35,1.35,0,0.5,0.5,0,1.5,1.5,0,3.85809,3.85809,0,6.222,6.222,0
</span></code></pre></td></tr></table></div></figure>


<p>The file is very long. In fact there are four separate CSV files crammed into
this one long CSV file. In the next blog post we&#8217;ll examine exactly how to
unzip the file you just downloaded with Python and then use one of these CSV
files.</p>

<p>If you want to be emailed when the next blog is ready, just enter your email
<a href="#register">up the top &rarr;</a>. We&#8217;ll only email you when a new blog is ready
and with tips on becoming an advanced Python using power systems engineer.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Matplotlib and PSSE]]></title>
    <link href="http://www.whit.com.au/blog/2012/07/matplotlib-and-psse/"/>
    <updated>2012-07-01T00:00:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/07/matplotlib-and-psse</id>
    <content type="html"><![CDATA[<p>Graphics, when used correctly, can be the difference between an outstanding
report and simply another piece of paper going around the office. The only
thing more professional than a nice graphic, is a graphic that is
automatically generated.</p>

<p>Exporting plots from the PSSE graphical interface can be a laborious task,
with little flexibility in the final result. If you are running <a
href="http://www.whit.com.au/blog/2011/07/run-psse-from-python-and-not-other-
way/">PSSE from Python</a>, you have the option of looking beyond PSSE for
tools to render your data.</p>

<p><a href="http://matplotlib.sourceforge.net/index.html"><strong>matplotlib</strong></a> is a
Python plotting tool which, given a little bit of effort, can make your life
easier by automating figure generation; spend the time to get it right once,
then generate the monthly figures with the press of a button.</p>

<p><strong>matplotlib</strong>&#8217;s syntax is closely aligned with <b>Matlab</b>&#8217;s, which is
fortunate if you are familiar with <b>Matlab</b>. If you are not familiar with
them, don&#8217;t worry, the <strong>matplotlib</strong> community has provide an excellent
<a href="http://matplotlib.sourceforge.net/users/pyplot_tutorial.html">tutorial</a>
and <a href="http://matplotlib.sourceforge.net/gallery.html">gallery</a>
displaying the immense possibilities of <strong>matplotlib</strong> (all examples come with
code included for you to use as a starting point).</p>

<p>I&#8217;ll use <strong>matplotlib</strong> to create this chart:</p>

<p><img src="https://lh6.googleusercontent.com/-G06Cv5E_MVg/T_Hl9yi5M2I/AAAAAAAAAME/zkRYNe5QdHA/w505-h379-k/qv-curve-bus-20001.png" title="'Resultant matplotlib chart'" ></p>

<p>It is the QV curve at bus 20001 (my favourite bus as it happens) and was
plotted from data kept in a CSV file (qv.csv).</p>

<div><script src='https://gist.github.com/3034594.js?file=qv.csv'></script>
<noscript><pre><code>V,Q
0.87,0
0.88,-50
0.89,-75
0.9,-90
0.905,-98
0.91,-103
0.92,-105
0.93,-106
0.94,-107
0.95,-107
0.96,-108
0.97,-105
0.98,-80
0.99,-50
1,-30
1.01,5
1.02,35
1.03,70
1.04,110
1.05,140
1.06,170
1.07,220
1.08,250
1.09,280</code></pre></noscript></div>


<p>Here is the code we used to create that chart.</p>

<figure class='code'><figcaption><span>QV curve plot with Matplotlib - plotqv.py </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
</pre></td><td class='code'><pre><code class='py'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">csv</span>
</span><span class='line'>
</span><span class='line'><span class="kn">from</span> <span class="nn">pylab</span> <span class="kn">import</span> <span class="n">plot</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">show</span><span class="p">,</span> <span class="n">grid</span><span class="p">,</span> <span class="n">xlabel</span><span class="p">,</span> <span class="n">ylabel</span>
</span><span class='line'>
</span><span class='line'><span class="c"># CSV file in format: V, Q</span>
</span><span class='line'><span class="n">QV_CSVFILENAME</span> <span class="o">=</span> <span class="s">&#39;qv.csv&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span><span class='line'>  <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">QV_CSVFILENAME</span><span class="p">)</span> <span class="k">as</span> <span class="n">qvcsvfile</span><span class="p">:</span>
</span><span class='line'>      <span class="n">reader</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">qvcsvfile</span><span class="p">)</span>
</span><span class='line'>      <span class="c"># skip header row.</span>
</span><span class='line'>      <span class="n">header</span> <span class="o">=</span> <span class="n">reader</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
</span><span class='line'>      <span class="n">voltage_and_reactive</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">reader</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="c"># now convert the voltages and power values to floats.</span>
</span><span class='line'>  <span class="n">voltages</span><span class="p">,</span> <span class="n">reactive</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>
</span><span class='line'>  <span class="k">for</span> <span class="n">voltage</span><span class="p">,</span> <span class="n">q</span> <span class="ow">in</span> <span class="n">voltage_and_reactive</span><span class="p">:</span>
</span><span class='line'>      <span class="n">voltages</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">voltage</span><span class="p">))</span>
</span><span class='line'>      <span class="n">reactive</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">q</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'>  <span class="c"># now make the chart.</span>
</span><span class='line'>  <span class="n">plot</span><span class="p">(</span><span class="n">voltages</span><span class="p">,</span> <span class="n">reactive</span><span class="p">,</span> <span class="s">&#39;-o&#39;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">title</span><span class="p">(</span><span class="s">&quot;QV curve for bus number 20001&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">ylabel</span><span class="p">(</span><span class="s">&quot;Reactive Power [MVAr]&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">xlabel</span><span class="p">(</span><span class="s">&quot;Voltage [pu]&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">grid</span><span class="p">()</span>
</span><span class='line'>  <span class="n">show</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
</span><span class='line'>  <span class="n">main</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>I&#8217;m using the <code>pylab</code> module of <strong>matplotlib</strong>. The <code>pylab</code> module most
closely resembles <strong>Matlab</strong> code so its a really familiar place to
start learning how to use <strong>matplotlib</strong>.</p>

<p>The first two sections open up the CSV file and convert it into
a list of <code>voltage</code> and <code>reactive</code> floating point values.</p>

<p>Now, I&#8217;ll pull a section of that code out so that we can look closely:</p>

<figure class='code'><figcaption><span>creating the chart  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>   <span class="c"># now make the chart.</span>
</span><span class='line'>  <span class="n">plot</span><span class="p">(</span><span class="n">voltages</span><span class="p">,</span> <span class="n">reactive</span><span class="p">,</span> <span class="s">&#39;-o&#39;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">title</span><span class="p">(</span><span class="s">&quot;QV curve for bus number 20001&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">ylabel</span><span class="p">(</span><span class="s">&quot;Reactive Power [MVAr]&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">xlabel</span><span class="p">(</span><span class="s">&quot;Voltage [pu]&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">grid</span><span class="p">()</span>
</span><span class='line'>  <span class="n">show</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>Thats the code that actually turns the lists of <code>voltages</code> and <code>reactive</code>
values into a chart. The functions describe themselves pretty well.
At the end of the routine <code>show</code> will pop up an interactive graph.</p>

<p>With the interactive graph you can:</p>

<ul>
<li>zoom in and out;</li>
<li>pan around; and</li>
<li>export the chart to an image file.</li>
</ul>


<p>If you haven&#8217;t ever used <strong>matplotlib</strong> go ahead and try this example out.
Before you do run the Python code here, just make sure you have both
<a href="http://matplotlib.sourceforge.net/index.html"><strong>matplotlib</strong></a> and
<a href="http://numpy.scipy.org/"><strong>numpy</strong></a> installed. Install <strong>numpy</strong> first because
matplotlib <em>definitely</em> needs it and will not install without it.</p>

<p>You&#8217;ve seen how easy it can be to start making your own charts with
<strong>matplotlib</strong>.  The quality of the resulting images is really exceptional.
We&#8217;ve used them throughout many industry published documents. If you have any
questions about making your own charts, jump onto our
<a href="http://psspy.org/psse-help-forum/">forum for power systems engineers</a> we&#8217;ll help you out.</p>

<p>If you made it this far, you must be pretty keen on Python. We are too! Let us
update you when we have something new to say about Python and Power Systems (semi regularly).
<a href="#register">Get Python Tips (subscribe on the right) &rarr;</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sri Lanka strengthens economy by installing renewable energy sources]]></title>
    <link href="http://www.whit.com.au/blog/2012/05/sri-lanka-strengthens-economy-by/"/>
    <updated>2012-05-26T00:00:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/05/sri-lanka-strengthens-economy-by</id>
    <content type="html"><![CDATA[<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-SqFAHr426H8/T797nbPNihI/AAAAAAAAwCM/3zQiVwGmKjk/s1600/photo.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="295" src="http://3.bp.blogspot.com/-SqFAHr426H8/T797nbPNihI/AAAAAAAAwCM/3zQiVwGmKjk/s320/photo.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sri Lanka&#8217;s demand for electricity is growing quickly</td></tr>
</tbody></table>


<p>Sri Lanka&#8217;s peak electricity demand of 2000 MW is growing at a rapid 5%-8%
every year.</p>

<p>To keep pace with the increase, the<a href="http://www.ceb.lk/"> Ceylon
Electricity Board (CEB)</a> have developed a clever plan.  Over the next 10
years, over 400 MW of mini hydro and wind farms will be installed. It is
anticipated the additional generation will meet the increased demand levels
and reduce Sri Lanka&#8217;s dependance on foreign fossil fuel sources, such as
coal, natural gas and petroleum.</p>

<p>Sri Lanka currently has over 200 MW of mini hydro power stations installed,
which are not dispatched centrally, but shown as a reduction in demand.
Additionally, there is 30 MW of wind generation installed and another 60 MW
soon to be connected.</p>

<p>We met with Mr. Shihan Diddeniya, CEO of renewable energy at CEB, to learn
more about Sri Lanka&#8217;s plan to increase the capacity of intermittent renewable
generation.</p>

<h4>Rapid growth in demand</h4>

<p>Mr. Diddeniya explained that Sri Lanka currently has about 88%
electrification. That is, 88% of households in Sri Lanka have direct access to
the electricity grid.  The proportion of electrified homes is growing quickly
with complete electrification likely to occur over the next few years. The
demand growth rate is a staggering 8% and once total electrification is
complete, growth will remain at a high 5%.</p>

<h4>A surplus of generation at low demand periods</h4>

<p>Shihan told of how the challenge for Sri Lanka is not with fault level
contributions from embedded mini hydros or building lines to remote wind
farms. He emphasized Sri Lanka&#8217;s challenge is with excess generation
capacity during low demand periods where electricity usage drops dramatically
below the 2000 MW peak to 860 MW.</p>

<p>Mini hydro and wind power plant output cannot be reduced because their power
is given first preference. As an example, if run of the river mini hydro and
wind power plants were to be producing 400 MW, then only 460 MW remains to be
supplied by thermal coal stations. The surplus generation could be resolved by
switching off coal fired stations.  But coal power stations are limited in
their ability to switch on and off quickly, it may take days for a coal power station to run at full capacity from a cold start.</p>

<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-BaUsYkBUgAM/TWETKJHSvtI/AAAAAAAADAs/v9NhScAQEoY/s1600/sl+169.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="213" src="http://2.bp.blogspot.com/-BaUsYkBUgAM/TWETKJHSvtI/AAAAAAAADAs/v9NhScAQEoY/s320/sl+169.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sri Lanka will soon have 100% electrification</td></tr>
</tbody></table>


<h4>A new link to India</h4>

<p>A transmission interconnect between Sri Lanka and India, which has been
contemplated since the 70&#8217;s, is expected to be started after 2013. The 285km,
high voltage DC link will have a total capacity of 1000MW, to be installed in
two 500MW stages.</p>

<p>The extra capacity made available by this link will go a long way to relieve
the immediate pressures the grid is currently experiencing.</p>

<p>Mr. Diddeniya will raise funds to complete the new renewable energy projects
from local and international banks and investors during the next few years.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to save money with your new smart meter]]></title>
    <link href="http://www.whit.com.au/blog/2012/04/how-to-save-money-with-your-new-smart/"/>
    <updated>2012-04-19T00:00:00+10:00</updated>
    <id>http://www.whit.com.au/blog/2012/04/how-to-save-money-with-your-new-smart</id>
    <content type="html"><![CDATA[<p>This is a simple story about how <a href="http://twitter.com/Haydarkie">@haydarkie</a> (the little guy) was able to notch up an incredible victory. He claimed his data back from the electricity companies. We&#8217;ll show you the steps he took to get his energy data and save big dollars on his energy bill.</p>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
 <img src="http://2.bp.blogspot.com/-ssjSYIy5ByE/T4o9XCgpbyI/AAAAAAAAAGU/2frFXS19Oo8/s1600/smart-meter.jpg" width="300" title="An old fashioned smart meter" >
</td></tr><tr><td style="text-align: center; width: 400px;">These old style meters only report your electricity once in three months. Smart meters record monitor your electricity every half hour. </td></tr></tbody></table>


<h4>Do you have a smart meter?</h4>

<p>Families commonly ask &#8220;How do I know if we have a smart meter?&#8221; The answer is that you are notified well in advance by your retailer that the installation will take place, and information will be left for you in your mailbox following the installation.&nbsp;Our story begins with the installation of a&nbsp;<a href="http://en.wikipedia.org/wiki/Smart_meter#Australia">smart meter</a>&nbsp;at the little guy&#8217;s family house.</p>

<h4>Why is the data valuable?</h4>

<p>Having worked in the industry, the little guy knew that the smart meter data was extremely valuable. With it he could shop around and get a better deal on his electricity - saving up to $100 / year on his bill. He can also see when he uses the most electricity, and whether or not it is during the most expensive part of the day, where customers are slugged double the price [1].</p>

<p>Here is how he got an Excel Spreadsheet of the valuable smart meter output emailed to him directly every quarter.</p>

<h4>Contact his electricity company by email</h4>

<p>Let them know you have a smart meter installed, you are a happy customer and would like to have regular access to your energy usage so you can save on your energy bill.</p>

<p>Here are the contact details of some of the retailers:</p>

<ul>
<li>Red Energy:&nbsp;<a href="mailto:enquiries@redenergy.com.au" title="Email Red">enquiries@redenergy.com.au</a></li>
<li>Origin Energy:&nbsp;<a href="https://www.originenergy.com.au/3244/Interval-meter-data-request" rel="nofollow">https://www.originenergy.com.au/3244/Interval-meter-data-request</a></li>
<li>Tru Energy:&nbsp;<a href="https://secure.truenergy.com.au/customerforms/LodgeEnquiry.aspx" rel="nofollow">https://secure.truenergy.com.au/customerforms/LodgeEnquiry.aspx</a></li>
<li>AGL:&nbsp;<a href="https://online.agl.com.au/enquiry_form.do" rel="nofollow">https://online.agl.com.au/enquiry_form.do</a></li>
</ul>


<p>Bear in mind many retailers haven&#8217;t had a great deal of experience with smart meters yet, and may not have the systems in place to send you data in a timely manner.</p>

<h4>Gently remind them of their obligations under the Retail Code</h4>

<p>The little guy got pushback from his retailer who claimed there was no requirement to send data more than once per year. <em>That was the old rule</em>, now there is a new rule that says they must provide whenever you request it and no mention of payments being necessary. Be brave, ask for them to send your data every day. For them, sending it once a month (by comparison) is a good compromise.</p>

<h4>What can you do with your data?</h4>

<table cellspacing="0" cellpadding="0" style="float:right; margin-left: 1em;"><tbody><tr><td style="text-align: center;">
  <img src="http://4.bp.blogspot.com/-ln19fXpQo9I/T4o4W6TQCLI/AAAAAAAAAGM/Yvp0-fhnoJA/s320/chart_1(1).png" width="300">
 </td></tr><tr><td style="text-align: center; width: 300px;">Do you use electricity during the most expensive part of the day?<a href='http://4.bp.blogspot.com/-ln19fXpQo9I/T4o4W6TQCLI/AAAAAAAAAGM/Yvp0-fhnoJA/s1600/chart_1(1).png'><br />[full size &rarr;] </a></td></tr></tbody></table>


<p>Run a chart like the one here showing the &#8216;average value&#8217; which is just your daily electricity use and your retailer&#8217;s time of use pricing plans in red. The huge jump in the red line is where you&#8217;ll pay the most to your electricity company.</p>

<p>Shop your data around, get together with 30 or so other little guys and form a cartel. You can shop the business of 30 people better than you can individually. This is what the big players like 7/11 and McDonalds do to save a fortune on their electricity costs.</p>

<p>Do you have any success stories about getting your data? Do you want to see your family or small business energy use on a chart like the one above? Leave a comment or email us directly at <a href="mailto:hello@whit.com.au">hello@whit.com.au</a>.</p>

<p>[1] <strong>time of use pricing</strong>. Most of you won&#8217;t be on a <em>time of use</em> pricing plan yet because many retailers have been slow to introduce these plans. Your current plan is likely to be one where you pay a flat rate (say 21 cents / kWh) all day and all year round - even during winter when the market prices for electricity is low and your retailer makes a fortune from you.</p>

<p>With the <em>time of use</em>&nbsp;plans you pay 10 cents / kWh over night, 18 cents during most of the day and 40 cents in the afternoon. &#8220;Complicated?&#8221;, yes it is complicated, but you could save a lot of money every year if you avoid using electricity during the afternoon. The red line in the chart above shows the price difference throughout a day. I have heard that these plans are a year or two away and seasonal pricing may take even longer to introduce.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Silencing PSSE output]]></title>
    <link href="http://www.whit.com.au/blog/2012/03/silencing-psse-output/"/>
    <updated>2012-03-20T00:00:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/03/silencing-psse-output</id>
    <content type="html"><![CDATA[<blockquote><p>Silence!</p><footer><strong>Thor</strong> <cite>2011</cite></footer></blockquote>


<p>PSSE prints a voluminous amount of information to the command line when you
are running a program. Do you remember seeing this when you start PSSE up?</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>PSS«E Version 32
</span><span class='line'>Copyright (c) 1976-2012
</span><span class='line'>Siemens Energy, Inc.,
</span><span class='line'>Power Technologies International (PTI)
</span><span class='line'>This program is a confidential unpublished work created and first
</span><span class='line'>licensed in 1976. It is a trade secret which is the property of PTI</span></code></pre></td></tr></table></div></figure>


<p>We will show you a little function that you can use to selectively turn off
this output (and other PSSE output) or redirect it to a log file.</p>

<p>This blog post is in response to a question by chip on the <a
href="http://psspy.org/psse-help-forum/question/27/silencing-psse-
stdout">python for power systems engineers</a> forum. Chip wanted to ignore
some of the output that PSSE was printing without ignoring <strong>all</strong> of the
program&#8217;s output.</p>

<figure class='code'><figcaption><span>silence.py</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">contextlib</span> <span class="kn">import</span> <span class="n">contextmanager</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">sys</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">os</span>
</span><span class='line'>
</span><span class='line'><span class="nd">@contextmanager</span>
</span><span class='line'><span class="k">def</span> <span class="nf">silence</span><span class="p">(</span><span class="n">file_object</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
</span><span class='line'>    <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd">    Discard stdout (i.e. write to null device) or</span>
</span><span class='line'><span class="sd">    optionally write to given file-like object.</span>
</span><span class='line'><span class="sd">    &quot;&quot;&quot;</span>
</span><span class='line'>    <span class="k">if</span> <span class="n">file_object</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
</span><span class='line'>        <span class="n">file_object</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">devnull</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="n">old_stdout</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
</span><span class='line'>    <span class="k">try</span><span class="p">:</span>
</span><span class='line'>        <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">file_object</span>
</span><span class='line'>        <span class="k">yield</span>
</span><span class='line'>    <span class="k">finally</span><span class="p">:</span>
</span><span class='line'>        <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">old_stdout</span>
</span></code></pre></td></tr></table></div></figure>


<p>The function <code>silence</code> can be used to selectively turn off PSSE output printing in your program. Use it like this:</p>

<figure class='code'><figcaption><span>using silence</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">with</span> <span class="n">silence</span><span class="p">():</span>
</span><span class='line'>  <span class="n">psspy</span><span class="o">.</span><span class="n">psseinit</span><span class="p">(</span><span class="mi">10000</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Printing from within the context block (the <code>with</code> statement) will be ignored.
(Note that we have
<a href="http://www.whit.com.au/blog/2012/01/how-max-buses-setting-affects-your-code/">initialised PSSE with buses</a>
set to ten thousand - based on our research of the optimal bus number).</p>

<p>What if you must redirect the PSSE output to a file? Got you covered. Use the
silence function like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">psse_log</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;psse_logfile.log&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span>
</span><span class='line'><span class="k">with</span> <span class="n">silence</span><span class="p">(</span><span class="n">psse_log</span><span class="p">):</span>
</span><span class='line'>  <span class="n">psspy</span><span class="o">.</span><span class="n">psseinit</span><span class="p">(</span><span class="mi">10000</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>There are more juicy details about how the context manager works on the forum:
<a href="http://psspy.org/psse-help-forum/question/27/silencing-psse-
stdout/">Silencing PSSE Stdout</a></p>

<p><strong>edit:</strong> You must also redirect PSSE output to Python using the <code>redirect</code>
module included with every PSSE installation:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">redirect</span>
</span><span class='line'><span class="n">redirect</span><span class="o">.</span><span class="n">psse2py</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="n">psse_log</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;psse_logfile.log&#39;</span><span class="p">,</span> <span class="s">&#39;w&#39;</span><span class="p">)</span>
</span><span class='line'><span class="k">with</span> <span class="n">silence</span><span class="p">(</span><span class="n">psse_log</span><span class="p">):</span>
</span><span class='line'>  <span class="n">psspy</span><span class="o">.</span><span class="n">psseinit</span><span class="p">(</span><span class="mi">10000</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How the max buses setting affects your code]]></title>
    <link href="http://www.whit.com.au/blog/2012/01/how-max-buses-setting-affects-your-code/"/>
    <updated>2012-01-30T00:00:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/01/how-max-buses-setting-affects-your-code</id>
    <content type="html"><![CDATA[<blockquote><p>..when you have eliminated the impossible, whatever remains, however improbable, must be the truth</p><footer><strong>Sherlock Holmes</strong> <cite>The Sign of the Four</cite></footer></blockquote>


<p>This is a story about <code>psspy.psseinit</code> and how its <code>buses</code> argument is not so
innocent and will one day commit a terrible crime on your study.</p>

<p>Have you ever sat and wondered why PSSE insists on asking for a <code>buses</code>
argument when initialising? Did you notice that it isn&#8217;t optional? I&#8217;ve sat at
my computer many times thinking: &#8220;Will I need 300, 1000 or 10,000 buses?&#8221;</p>

<h4>What is the buses argument?</h4>

<p>According to the API guide in section 12.13: <em>The buses argument is the
requested bus size</em>. Not especially helpful, so in plain english we say the
<code>buses</code> argument is:</p>

<blockquote><p>buses - The maximum number of buses allowed in your study</p></blockquote>


<h4>Why have a maximum number?</h4>

<p>PSSE was written in a time when creating a busmatrix in the computer&#8217;s memory
was a difficult task. In those days, once you had picked a matrix size, thats
was it, there was no second chance to resize it. So picking the maximum number
of buses was very important. Choose a huge matrix and your poor computer&#8217;s
memory would fill up, choose one too small then the matrix wouldn&#8217;t fit all of
your buses.</p>

<h4>PSSE uses more memory when you initialise more buses</h4>

<p>We decided to put this to the test. The PSSE documentation states that the
maximum number of buses it can handle is 150,000. So we initialised PSSE over
and over and over with a maximum of 10 buses up to 1 million and measured how
much memory it used.</p>

<p><img src="http://4.bp.blogspot.com/-pSBP_uzKQ6Y/TyZK7LcboDI/AAAAAAAAAEk/wuWpGnEX-HE/s1600/chart_1.png" title="'Memory usage increases as PSSE bus size increases'" ></p>

<p>The results are clear, allocating more maximum buses uses more memory until 150,000 when allocating more buses has no effect - because the additional buses beyond 150,000 are ignored.</p>

<h4>The terrible crime and how to avoid it</h4>

<p>Because of the history when PSSE was written, <strong>you must pick the correct
size.</strong> If you pick a maximum number of 100 buses, and your raw file has 120
buses <strong>then 20 of those buses will not be loaded</strong>. Unlike for raw files,
our experiments have shown that loading a saved case (.sav file) resets the
maximum bus size to the one used in the sav case.</p>

<p>So some advice: be sure to set a maximum bus size large enough to handle your
system size, but not too large otherwise PSSE will gobble up all of your
memory. <strong>We suggest that 10,000 buses is enough</strong>, if you regularly use
more than 10,000 buses let us know in the comments.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Find Your PSSE Path, Young Grasshopper]]></title>
    <link href="http://www.whit.com.au/blog/2012/01/find-your-psse-path-young-grasshopper/"/>
    <updated>2012-01-17T00:00:00+11:00</updated>
    <id>http://www.whit.com.au/blog/2012/01/find-your-psse-path-young-grasshopper</id>
    <content type="html"><![CDATA[<p>PSSE doesn&#8217;t make it easy to import and start using its Python API, <code>psspy</code>.
We covered how and why it is
<a href="http://www.whit.com.au/blog/2011/07/run-psse-from-python-and-not-other-way/">beneficial to use Python to drive PSSE</a>
, but the implementation had a few limitations. To be specific, the
necessary code to get it all working is a bit of black magic for the
uninitiated and the PSSE install location is hard coded into the script. We
discuss here a new method to get it to work on any setup with a single line of
code. Best of all, it is free and and open source.</p>

<p>The following lines of code are the black magic which we aim to address:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">sys</span>
</span><span class='line'><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">r&quot;C:\Program Files\PTI\PSSE32\PSSBIN&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;PATH&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="s">r&quot;C:\Program Files\PTI\PSSE32\PSSBIN;&quot;</span>
</span><span class='line'>                        <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;PATH&#39;</span><span class="p">])</span>
</span></code></pre></td></tr></table></div></figure>


<p>The above code only works on systems where the <code>PSSBIN</code> folder is located at
<code>"C:\Program Files\PTI\PSSE32\PSSBIN"</code>. If you were to share this script
with a colleague who was running on 64 bit install of windows (<code>"C:\Program
Files x86\PTI\PSSE32\PSSBIN"</code>) or a different version of PSSE
(<code>"C:\Program Files\PTI\PSSE33\PSSBIN"</code>), then the script would fail to
run.</p>

<p><code>pssepath</code>
solves this problem by automatically configuring these settings with a single
line of code. The project is hosted on <a
href="https://github.com/danaran/pssepath">github</a> and based on an idea
proposed by <a href="http://psspy.org/psse-help-
forum/users/6/chip/">chip</a> in our
<a href="http://psspy.org/">Python for power systems engineers Q&amp;A site</a>
(<a href="http://psspy.org/psse-help-forum/question/3/how-do-i-import-the-psspy-module-in-a-python?answer=7#answer-container-7">the answer that started it all</a>).
 The goal is to be able to setup and import
<code>psspy</code> on any computer with three simple lines of code:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">pssepath</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">pssepath</span><span class="o">.</span><span class="n">add_pssepath</span><span class="p">()</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">psspy</span>
</span></code></pre></td></tr></table></div></figure>


<p>Thats it! Now you can share your code with anyone and get back to doing productive work!</p>

<p>To use <code>pssepath</code>, download the zip from the <a
href="https://github.com/danaran/pssepath/downloads"><code>pssepath</code> download</a>,
extract the <code>pssepath.py</code> file and place it in the same folder as the script
you want to run. We are working to make installation global (so you won&#8217;t have
to place it in every folder) and much easier, so check back soon for
developments.</p>

<p>The code is licensed to be compatible for use within a commercial environment.
If you have any problems using <code>pssepath</code>, let us know about your difficulty
and we will work with you to get it fixed for everyone. Alternatively, as the
project is open source, you are free to take our code and do whatever you want
with it (but if you do something really cool, please share it with the rest of
us :)</p>
]]></content>
  </entry>
  
</feed>
