Sunday, August 7, 2011

How to make high-speed rail stack-up

On the face of it, the latest of a long line of studies into fast rail appears to show, yet again, that it is going to be hard to justify the huge up-front capital costs. An estimated cost of $80 billion (give or take $20-odd billion, but who cares about loose change?), which is not going to be recouped in any significant way from fares. So lets not bother, right?

But hang on, aren't we missing something here? Well, only the main cost-recovery avenue -- value (re)capture. The idea is hardly new, but for some reason I can't fathom it is rarely discussed in detail in these fast rail feasibility studies. For those unfamiliar with the idea, it's quite simple.  The government is going to shell out huge buckets of money building a high-speed rail line. Anyone owning property near the rail stations will immediately see the value of that property increase. Since these property owners haven't done anything themselves, and are just benefiting from the government's spending, it's fair for the government to recoup the increase. At this point people often start quibbling about difficulties in estimating the benefits, or object to trying to claw back money from old ladies who just happen to own a house near one of the stations. None of that is relevant except in political terms, and for the moment lets stay away from the politics: we can come back to that later.

So how important is value-capture, relative to fare-box revenue? Very. Lets do our own back-of-the envelope calculations and see. First up, lets simplify things just to make the case for value recapture clear. Let's just take the Sydney-Newcastle-Canberra section of the track. The best-guess cost for this in the most recent study is $29.3 billion; let's just call it $30 billion.

Total cost: $30 billion

A further simplification will help bring out my point, and allow us to avoid complicated calculations that just obscure my main point. Let's say that instead of linking Sydney, Canberra and Newcastle, we just build south-west from Sydney out to empty sheep paddocks near Golbourne, and North to some easily developable land near the Central Coast or Newcastle. So, we have two lines, with 4 stops along each line (as in the most recent study), and a train commute of 40 minutes or under for each station.

Now, suppose we develop a small 2km radius 'town' around each station. Since we've built out to sheep paddocks this should be no problem. A 2km radius town with 8 lots per hectare will give us 10000 lots in each town. How much would each lot be worth? With a sub-40minute commute to Sydney, I'd say at least three or four hundred thousand. But lets say after servicing and other costs, the net increase is $200k for each lot. So, 8 stations, 10000 lots per station, $200k per lot, gives us $16 billion dollars:

Land-capture capital recovery: conservatively, $16 billion

So with some pretty conservative assumptions we have recouped half the capital cost. Getting a little more creative should allow even greater cost recovery. Developing a 3km^2 town at each station, or developing at higher densities, are easy adjustments that would increase revenue and get you to near full cost-recovery without any fare-box revenue.

So what about fare-box revenue? In our 8 towns, with 10000 dwellings, lets say there are 10000 workers, 30% of which commute using the rail line, with the other 70% commuting by car or some other mode. So, 3000 workers in each town commuting each way 200 days a year gives us 9.6 million trips. Call it 10 million. Add another 10 million non-work trips. Say each trip costs $10. So, that's $200 million a year, or a 0.6% p.a. gross return on $30 billion invested, before we take into account operating costs. Fiddle with the above numbers any way you like, it wont change the fact that fare-box revenue is almost small enough to forget about altogether, and certainly much less important than value-capture as a funding mechanism.

Net fare-box revenue: approximately nil.

Bottom-line: if you want to fund high-speed rail, heck, in fact rail of any kind, you need to put value recapture front and centre of your approach to cost-recovery. Why isn't it already? Because property owners would prefer to pocket the benefits from the rail-line themselves, and many will fight tooth-and-nail to do so. Building the line to some empty sheep paddock mostly avoids this, because there are only a handful of large land-owners likely to be involved, and that's why I took that approach in the above example, but in reality there would be a lot of opposition to such a move ("It's crazy to build a rail line out to nowhere! We need to strengthen the centres we already have!"). And  if you do build to existing centres, it is politically difficult to claw back the increased land values (not that any Australian government have really tried very hard....). In fact, building the line out to empty paddocks is probably not the best plan, economically, anyway, provided that you have a mechanism to recoup the increased value from existing land-holders.

And the reason land-value capture works so well (if you can do it, politically), is because our dysfunctional planning systems have made supply of new dwellings, at low cost, so difficult. So there is a lot of suppressed demand for accessible locations. A rail line is, essentially, a way of 'manufacturing' new accessible locations. Releasing land on the urban fringe is not the same thing -- a point missed by many who claim that the fix to our housing supply problems is just to release more land. This would help a bit, but the real demand is not for land, but for dwellings with good accessibility (to jobs, and other things), and accessibility can only really be supplied by transport infrastructure.

As a final aside, some economists have pointed out that because the benefits of rail systems get capitalized into a relatively small number of land-holders, this makes rail distributively unfair, as costs are shared and benefits and concentrated. The benefits of a motorway, on the other-hand, are much more widely spread. This is a valid point, and can't be addressed without re-thinking value capture. Just to be clear: I'm not arguing for motorways here, just making it clear that making rail work requires us to have a discussion about the fairness of recouping private gains from public infrastructure investment.

Wednesday, May 4, 2011

Connecting to mysql from python the odbc way from mac

This post just describes how to set up python to talk to a mysql database on a mac. Written for reference, and for co-workers who will shortly need to do something like this.

I wanted to be able, in a python script, to talk to a remote MySQL database from my mac. As I went about this I found the documentation a little scattered -- I couldnt find a single page giving the instructions, and so I've just written up the steps here.

I assume that you have python installed already.

Step 1: Install pyodbc

First step is to install pyodbc if you havent got it installed already. I downloaded pyodbc from http://code.google.com/p/pyodbc/downloads/list (I downloaded the source distribution because there were no binaries for mac. The source distribution is the one that ends in .zip)

After unzipping this, going into the directory that is created by the unzip and typing python setup.py install at the command prompt should install everything without you needing to do anything else.

Step 2: Check that you have an odbc manager installed

pyodbc wont do all the work for you -- it relies on an odbc manager to ferry things back and forth to databases. On a Mac you should have an odbc manager installed already by default. My machine has one called iodbc: if I type iodbctest at the command prompt* I get the following:

iODBC Demonstration program
This program shows an interactive SQL processor
Driver Manager: 03.52.0607.1008

Enter ODBC connect string (? shows list):

If I then type '?' as suggested, I get an empty list... which explains that there are no drivers installed. What is a driver? Its a database-specific connector that lets the odbc manager talk to a particular database (MySQL, Postgresql, SQLServer, etc). So the last link required in the communication chain is a mysql driver.

* Apparently you can get to iodbc through Applications->Utilities as well if you want to look for it in the Mac GUI.

Step 3: Install your odbc drivers

OK, so we now need to install specific odbc drivers for each database we want to connect to. In this case, I'm just going to install MySQL. I grab the odbc driver from http://dev.mysql.com/downloads/connector/odbc (picking the Mac .dmg file just to make the installation easy). A few clicks on the .dmg file and the driver is installed.

I can check that it is installed by running iodbctest again from the command prompt. This time when I type '?' to see what drivers are installed I get:

Enter ODBC connect string (? shows list): ?

DSN | Driver
------------------------------------------------------------------------------
myodbc | MySQL ODBC 5.1 Driver

OK, so that completes the pipeline. Now in python I can use pyodbc, which talks to iodbc (or whatever ODBC manager you have installed), which uses the mysql odbc driver to talk to a MySQL database.

So lets do that and check that it works

Step 4: connect to your database from python

OK, so now we should be able to connect to your database in python.

But one last thing you need to do is to work out what connection string you need to connect to your database. A helpful resource with example connection strings can be found at http://www.connectionstrings.com/. Here is what I did in python to connect to my database:

>>> import pyodbc
>>> connstr="Driver={MySQL ODBC 5.1 Driver};Server=your.server.;Port=3306;Database=databasename;User=username; Password=nottelling;Option=3;"
>>> conn=pyodbc.connect(connstr)
>>>

and from here you can just play with the conn object as you like in python! So, for example, to look at a table:

>>> res = conn.execute("select * from sometable")
>>>for r in res:
>>>    print r.next()

Saturday, April 9, 2011

Rental yields will increase, but not the way they'd like....

In response a growing chorus of analysts pointing out that Australian property seems to have both limited prospects for capital growth and low rental yields, many property market boosters respond that yields will increase (even the boosters have given up spruiking capital growth as a reason to buy property -- that boat has sailed).

Now, for once I am in agreement with the property markets boosters -- yields must increase. But there are two ways for yields on residential property to increase. Increasing rents is one (and clearly the one the boosters have in mind). But falling prices will do the job just nicely also. Just saying.

newspapers snoozpapers

On a recent flight back from Perth, I found myself growing increasingly exasperated at the poor quality of the journalism in the two newspapers available -- the Fin Review and the Australian.

For some time I've been hoping, against all evidence to the contrary, that the Fin would not follow the Sydney Morning Herald's slide into mindless he-said she-said reporting. But reading the Fin during the last week has not been encouraging. Why read the Fin if not for some actual analysis? But what we get now on almost every issue are the verbatim opinions of pundits -- financial, political, social. Knowing what Bill Gross' views are on inflation and government indebtedness, while interesting, is complementary to, not a replacement for, detailed reporting.

The Saturday article on 'bond vigilantes' was especially unsatisfying -- with extensive quotes from 'senior bond traders' together with repetition of all the tired old news-bites about looming US inflation and sovereign debt concerns. Did the article contain any references to actual evidence or analysis enabling readers to evaluate such claims? US core inflation figures? Long term bond yields consistent with either rampant inflation or sovereign default? No, just appeals to financial market authority-figures.

This low-quality style of reporting has been prominent in real-estate journalism for a long time, where puff pieces quoting real estate agent and industry mouthpieces have forced those interested in any thoughtful analysis to other sources. (Leith van Onselin, for example, has posted manytimes on the issue -- such as here, here, and here).

As for the Australian, the problems there are quite different. Not being a regular reader, I was unprepared for the breadth and depth of the editorial lunacy, from Greg Sheridan's column railing against the economy wrecking carbon tax to Chris Merritt's nanny-state rant. In political and news sections, Peter van Onselin's column offered the only relief (Peter is Leith's brother -- there must be something in the genes). In Business, Glenda Korporaal's piece was also thoughtful and balanced enough to be out-of-place.

Not content with its plentiful home-grown lunacy, the Australian even found space to import some, with William McGurn's WSJ piece praising Paul Ryan's fairytale deficit reduction plan -- entirely neglecting to mention that the plan relies entirely on heroic assumptions (2.8% unemployment in 2021, anyone?).

I'm too young to become a grumpy old man about these things, but they're forcing my hand dammit!

Monday, August 2, 2010

Just a reminder to myself on converting between coordinate systems in ArcGIS.


I often want to convert data from one coordinate system into another, and I frequently forget how to do this. This is just a post to myself so that I remember how to do this..


Below is just a cached copy of this page, replicated here in case the original page goes away.....










Converting your vector files into different Coordinate Systems Using ArcGIS 8.2

EXAMPLE: converting NAD83 MTM ZONE8 to WGS84 UTM ZONE18

  1. open ArcToolBox
  2. choose Data Management Tools Projections Project Wizard (shapefiles, geodatabase)


  1. select the shapefile to be converted, then its original coordinate system will be list in the dialog. Click Next.

  1. define output file name and stored location; click NEXT.

  1. giving desired coordinate system; click Select Coordinates System

  1. click Select to define a new coordinate system

  1. choosing Geographic (lat/long) or Projected (x/y) coordinate system.

For WGS84 ZONE18N, choose Projected coordinate system UTM WGS84WGS84 UTM ZONE18N. Click NEXT.

  1. Detail information of WGS84 UTM ZONE 18N will be list in the dialog. Click NEXT

  1. A Geographic transformation (optional) will be required since (in this case) NAD27 and WGS84 are different datum. A list of option will be offered in the function; choose the newest transformation (or fit the case). Finally, your output file should be projected in the new coordinate system.

Tuesday, March 30, 2010

Schumacher's foresight and the folly of complex forecasting models

I've been reading Schumacher's "Small is Beautiful" recently -- quite an old book now but still worth a read. He writes very clearly, and the subject matter of the book is mostly still relevant, and the key ideas still thought-provoking. He shows uncommon foresight on a few topics. For example, he talks about the near certainly of a future where oil is scarce & expensive, and he was doing so before even the 1970's oil shocks. He also talks about the folly of eroding natural capital long before it was common to do this. But perhaps most interestingly, he identifies the process where a void in values (created by the decline of religion) was being filled by economics, and despite being an economist, he thought this dangerous. He thought it far safer to rely on traditional cultural & religious value systems than to subject everything to economic cost benefit analysis. I think this last point is especially interesting because, while most economists will probably baulk at it, recent events lend weight to Schumacher's view. For example, look at all the economic debate and analysis that has gone into climate change, and look where it has got us. Wouldn't we have done better developing a value system where caring for our planet was more than just an economic consideration, but something sacred?

Schumacher wasnt a hippy or anything either, nor was he a fuzzy-minded economist who hated the reduction of everything to numbers because he himself couldnt do any maths. In fact, he was a competent mathematician. This makes some of what he has to say about model-building in the later chapters of his book particularly interesting. Being a bit of a data-cruncher and model builder myself, I liked the quotes in particular, which are right on the money, and which I think should be compulsory reading for any model builder:

"Crude methods of forecasting ... are not likely to lead into the errors of spurious verisimilitude and spurious detailing -- the two greatest vices of the statistician. Once you have a formula and an electronic computer, there is an awful temptation to squeeze the lemon until it is dry and present a picture of the future which through its very precision and verisimilitude carries conviction. Yet a man who uses an imaginary map, thinking it a true one, is likely to be worse off than someone with no map at all; for he will fail to inquire wherever he can, to observe every detail on his way, and to search continuously with all his senses and all his intelligence for indications of where he should go.

The person who makes the forecasts may still have a precise appreciation of the assumptions on which they are based. But the person who uses the forecasts may have no idea at all that the whole edifice, as is often the case, stands and falls with one single, unverifiable assumption. He is impressed by the thoroughness of the job done, by the fact that everything seems to 'add up;, and so forth. If the forecasts were presented quite artlessly, as it were, on the back of an envelope, he would have a much better chance of appreciating their tenuous character and the fact that, forecasts or no forecasts, someone has to take an entrepreneurial decision about the unknown future."

I wish I could say I had never fallen for the temptation to go for a complex model with 'rich' outputs, when it would have been essentially as accurate, and less misleading, to present a few back of the envelope projections.....

Monday, March 8, 2010

More arcgisscripting hacking

As I mentioned in an earlier post, I've been fumbling around trying to learn how to get a python program that can talk to ARCGis. After getting around some initial irritations, I'm actually making some headway. I found this series of posts particularly helpful. As a reminder to myself, and as help for anyone else grappling with this, I'll post the first non-trivial script I've come up with here. This script is still pretty simple -- it opens up a shapefile and reads all the information associated with the shapefile. Here it is:



import arcgisscripting
import sys

#This is my first attempt to do some python
#scripting with ArcGIS Geocomputation object

#first we create the gis scripting object
gp = arcgisscripting.create(9.3)

gp.Workspace = "C:/tmp"
#allow old files to be overwritten
gp.OverWriteOutput = True

#lets print out some information about a layer
shapefile= "C:/tmp/test.shp"
desc = gp.Describe(shapefile)

#From Describe object
print desc.DataType
print desc.CatalogPath

#From FeatureClass object. The Describe object
#that is returned by the above call to Describe
#is also a 'FeatureClass' object. I havent quite
#got my head around the data model used by the
#geoprocessing object, so I don't quite understand
#how we know which fields are available and which
#arent after a call to describe.... but these work
#for the shape file I'm using.
print desc.ShapeType
print desc.FeatureType
print desc.ShapeFieldName

#list the fields. This is the same as
#returned by ListFields()
for f in desc.Fields:
....print " "+f.Name


#now go and read each line in the spatial
#data table associated with the shapefile.

#first we get a 'read' cursor
readCursor = gp.SearchCursor(shapefile)

#make sure we are at the start
readCursor.Reset()

#now go through and read (and print out) each row
row = readCursor.Next()
while (row != None):
....#print the contents of the row
....resstr = "ROW: "
....for f in desc.Fields:
........resstr = resstr + str(row.GetValue(f.Name)) + " , "
....print resstr

row = readCursor.Next()


#done!