30 Jan 2015
For converting between vector formats (shapefile, Mapinfo etc) you can use the
command line tool ogr2ogr as an alternative
to Universal Translator in Mapinfo. It’s really easy to use. Here’s how to
convert from shapefile to Mapinfo tab file:
ogr2ogr -f "MapInfo File" data.tab data.shp
Make a KML for use in Google Earth:
ogr2ogr -f KML data.kml data.shp
Back to shapefile from the KML:
ogr2ogr -f "ESRI Shapefile" data.shp data.kml
You get the hang of it. There’s a lot of formats, you can see the whole list by
typing ogr2ogr --formats
. ogr2ogr can also do other things like reprojecting
and clipping vector data. As an example, for using Google Earth you probably
want to use WGS84 instead of the usual MGA56. From doing way too much
converting between projections I know that the EPSG numbers for these are 4326
and 28356. So:
ogr2ogr -f KML -a_srs EPSG:28356 -t_srs EPSG:4326 data.kml data.shp
Note that converting from Mapinfo to shapefile can cause some grief since
Mapinfo files can have points/lines/polygons in the same file whereas
shapefiles can only have a single type of geometry. You’re probably better off
sticking with Universal Translator for this use case.
There’s also a tool for converting between raster formats (gdal_translate) but
it’s slightly harder to use (tends to mess up nodata values if you don’t
specify correctly).
14 Jan 2015
Getting started with Python and looking for a good setup? Or maybe experienced
Python-person looking to look down on someone else’s inferior setup? Either
way, this might be the page for you! Here I’ll describe my general setup for
writing world-changing software such as Todo for
Windows. I originally wrote it
after setting up the same environment on three of my co-workers’ computers -
like any good programmer, I’m lazy and try my best to “automate” everything (in
this case, “automate” just means “make someone else do it instead of me”).
##Editor
I like Sublime Text 3. It is technically in
beta, but works very well. It costs about $60, but has a free version that
very occasionally nags you to buy. I bought it after a while because I thought
it was really good. Get it.
Then install Package Control. It
looks a bit daunting, but all you have to do is paste some text into the
Sublime command prompt (accessed with ctrl+`
). Then we get an excellent
package management system, which is easily accessed with ctrl+shift+p
, start
typing “install package” until it comes up. Then you get a list of packages
available. Get these to start with:
- SublimeCodeIntel (gives you autocomplete and clickable functions)
- SublimeLinter (gives you code linting - shows you any syntax errors you make)
- SublimeLinter-pyflakes (python-specific linting)
- AdvancedNewFile (
ctrl+alt+n
to easily create new files/folders)
- SidebarEnhancements (gives a better context menu when you right click on
sidebar items)
- Theme - Spacegray (just looks nicer)
There are a few other good ones too, have a look around. Most of these work out
of the box, but SublimeLinter needs a bit of extra work/love. You also have to
install the Python pyflakes package and make sure it is on your system PATH
.
See the section on Python packages for details on how to do that.
Here are some things I like about Sublime Text:
- Easy access to all commands with
ctrl+shift+p
ctrl+p
for easy switching between files
ctrl+click
to make multiple cursors
ctrl+D
to select next occurrence of a word/character
alt+f3
to select all occurrences
ctrl+l
to select lines, then ctrl+shift+l
to make cursors on each line
- Making snippets
- Split panes (and other options) with
alt+shift+2
- The find (
ctrl+shift+f
) functionality for all open files or all files in
directory
- Swapping lines with
ctrl+shift+up
or down
arrow
- Pretty good (though far from perfect) vim bindings
Here is my Settings (User)
file:
{
"auto_complete_commit_on_tab": true,
"color_scheme": "Packages/User/base16-eighties.dark (SL).tmTheme",
"detect_slow_plugins": true,
"ensure_newline_at_eof_on_save": true,
"find_selected_text": true,
"fold_buttons": false,
"font_face": "consolas",
"font_size": 10,
"highlight_line": false,
"ignored_packages":
[
],
"rulers":
[
79
],
"soda_classic_tabs": true,
"soda_folder_icons": true,
"spell_check": false,
"theme": "Spacegray Eighties.sublime-theme",
"translate_tabs_to_spaces": true,
"trim_trailing_white_space_on_save": true,
"vintage_start_in_command_mode": true,
"word_wrap": false
}
##Source Control
I like git for source control. It’s basically
standard these days, in large part due to GitHub.
Get it by installing GitHub for Windows which is
an easy to use (but somewhat limited in functionality - I still like it because
it’s intuitive and very pretty) GUI for git.
GitHub is really good, but it’s only free if all your code repositories are
public, which we can’t always do. There’s another site which is also quite
good, BitBucket, that allows you to have private
repositories for free. Get an account there. It is still possible to use the
GitHub for Windows app to push code to BitBucket.
##Python Packages
For packages, first see if it’s available from
here. If it’s not, use pip
to
install. To do this, download and install pip
from the above site, then add
C:\Python27\Scripts
to your PATH
environment variable. You do this by
pressing the Windows key, starting to type “environment variable” until the
option “Change the system environment variables” comes up. Scroll to the PATH
variable and append C:\Python27;C:\Python27\Scripts
to the end. Now you can
start a command line prompt and type pip install <package>
and it will be
installed into your Python folder for future use in all your projects. If you
have SublimeLinter with Pyflakes installed, it should also work now.
The reason we have to download precompiled installers for some packages is that
pip
doesn’t work on Windows for packages that have extensions written in C,
which practically all the scientific computing packages do. But for most things
it will work fine (requests
, click
, and so on).
The Python standard library is pretty extensive, and will have the tools to do
most things you will want to do. But, in many cases, someone else has written a
library that is easier to use and, well, more “Pythonic” (a word you will come
across here and there). Here are some of my go-to external libraries:
- pandas – If you do any scientific programming, this is where to start
- click – super-easy command-line interfaces (over
argparse
/optparse
)
- funcy – intuitive, powerful manipulation of data structures and functions
- requests – the best way to make HTTP requests (over
urllib3
/httplib
)
- unipath – file and folder path manipulation made easy (over
os.path
)
I use these all the time. They make Python much more enjoyable to write.
29 Dec 2014
I’ve written an API with Flask that takes some input parameters, does some
calculations and returns JSON. Pretty standard. Today I wanted to change it so
that some of the parameters could be provided as lists and the API would return
results for all combinations. So the original query string would look something
like this:
which would return:
{
"a": 10,
"b": 20,
"c": "hello",
"result": 30
}
And I wanted to be able to do this:
which should return:
{
"data": [
{
"a": 10,
"b": 20,
"c": "hello",
"result": 30
},
{
"a": 10,
"b": 30,
"c": "hello",
"result": 40,
},
{
"a": 20,
"b": 20,
"c": "hello",
"result": 40,
},
{
"a": 20,
"b": 30,
"c": "hello",
"result": 50,
}
]
}
- step1: arrays
- step2: ast.literal_eval - feels pretty hacky
- step3: notice what the
requests
module does
- step4: facilitate that
- result: clearer but more verbose
10 Nov 2013
Recently I made a site which had a form with, amongst other things, latitude
and longitude coordinates as an input.
class InputDataForm(Form):
lat = FloatField('Latitude', default=-30,
validators=[validators.InputRequired()])
lon = FloatField('Longitude', default=150,
validators=[validators.InputRequired()])
I am using a simple validator for making sure that something is input into the
form. But, I also want to make sure that the coordinates fall within a polygon,
which requires access to both field values, and hence cannot be written as a
normal field validator. I have to add custom validation functionality to the
whole form. Flask-WTF lets me do this by overriding the validate method on the
InputDataForm class.
def validate(self):
def is_in_a_region(lat, lon, regions):
p = Point(lon, -abs(lat))
for r in regions:
if p.within(r.to_shapely()):
return True
return False
rv = Form.validate(self)
if not rv:
return False
regions = Region.query.all()
if not is_in_a_region(self.lat.data, self.lon.data, regions):
self.lat.errors.append('Invalid coordinates')
self.lon.errors.append('Invalid coordinates')
return False
return True
The is_in_a_region
function is a bit unwieldy here, since I am not using a
spatially aware database (like PostgreSQL/PostGIS) but plain SQLite with a
string field for storing the geometry as WKT. Still, it does the job.